Menu
Coddy logo textTech

메서드에서의 self

Coddy Ruby 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 9번째.

메서드 내부에서는 클래스에 setter name=가 있더라도 name = value는 항상 지역 변수를 만듭니다. setter를 호출하려면 수신자를 명시하세요: self.name = value:

class Player
  attr_accessor :level

  def initialize
    @level = 1
  end

  def broken_level_up
    level = level + 1
  rescue NoMethodError
    puts "level is a new local variable here, still nil"
  end

  def level_up
    self.level = level + 1
  end
end

p1 = Player.new
p1.broken_level_up
p1.level_up
puts p1.level

출력:

level is a new local variable here, still nil
2

독자는 self.가 필요하지 않습니다. level과 self.level은 같은 메서드를 호출합니다. 일반적인 스타일에서는 Ruby가 self.를 필요로 하는 경우, 즉 setter 앞에서만 이를 작성합니다:

class Rect
  attr_accessor :w, :h

  def initialize(w, h)
    @w = w
    @h = h
  end

  def area
    w * h
  end

  def double!
    self.w = w * 2
    self.h = self.h * 2
    self
  end
end

puts Rect.new(2, 3).double!.area

출력:

24

self.를 사용해 initialize에서 setter를 호출하면 새 객체도 이후 변경과 동일한 검사를 통과하므로, 규칙이 한 곳에 모입니다:

class Product
  attr_reader :price

  def initialize(price)
    self.price = price
  end

  def price=(value)
    raise ArgumentError, "price must be positive" if value <= 0

    @price = value
  end
end

puts Product.new(5).price
begin
  Product.new(0)
rescue ArgumentError => e
  puts e.message
end

출력:

5
price must be positive

self가 무엇을 의미하는지는 코드가 실행되는 위치에 따라 달라집니다. 인스턴스 메서드 내부에서는 인스턴스를 의미하고, 모든 메서드 외부의 클래스 본문에서는 클래스 자체를 의미합니다:

class Robot
  puts "in the class body, self is #{self}"

  def whoami
    "in a method, self is a #{self.class}"
  end
end

puts Robot.new.whoami

출력:

in the class body, self is Robot
in a method, self is a Robot
challenge icon

챌린지

쉬움

Account 클래스에는 0보다 작은 값에 대해 ArgumentError를 발생시키며 balance cannot be negative를 전달하는 사용자 지정 setter balance=가 있습니다. initialize(owner, balance), deposit(amount), withdraw(amount)을 완성하여 잔액의 모든 변경이 self.를 사용해 해당 setter를 거치도록 하세요. 시작 잔액도 포함됩니다.

제공된 코드는 소유자와 시작 잔액을 읽은 다음 +n(입금) 또는 -n(출금) 명령을 읽습니다. 각 명령 후 Ada: 120을 출력하거나, 오류 메시지와 변경되지 않은 잔액을 출력합니다. 시작 잔액이 유효하지 않으면 오류 메시지만 출력합니다.

작성한 코드는 account.rb에 넣으세요. main.rb에는 제공된 입력/출력 코드가 있으며 수정할 수 없습니다.

직접 해보기

require_relative 'account'

# 제공된 입력/출력 코드: 그대로 유지하세요
input = []
while (line = gets)
  input << line.chomp
end
begin
  account = Account.new(input[0], input[1].to_i)
  input.drop(2).each do |cmd|
    begin
      amount = cmd[1..].to_i
      cmd.start_with?("+") ? account.deposit(amount) : account.withdraw(amount)
    rescue ArgumentError => e
      puts e.message
    end
    puts "#{account.owner}: #{account.balance}"
  end
rescue ArgumentError => e
  puts e.message
end
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Ruby 컴파일러