メソッド内のself
CoddyのRubyジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 9/57。
メソッド内では、クラスにセッター name= がある場合でも、name = value は常にローカル変数を作成します。セッターを呼び出すには、レシーバーを記述します: 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. を記述します。
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出力:
24self.を付けてinitializeからセッターを呼び出すと、新しいオブジェクトにも後の変更と同じチェックが適用されるため、ルールを1か所に集約できます。
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 positiveself が何を指すかは、コードがどこで実行されるかによって異なります。インスタンスメソッド内ではインスタンスを指し、すべてのメソッドの外にあるクラス本体内では、クラス自体を指します。
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チャレンジ
簡単Account クラスには、0 未満の値に対して balance cannot be negative という ArgumentError を発生させるカスタムセッター balance= があります。initialize(owner, balance)、deposit(amount)、withdraw(amount) を完成させ、開始時の残高を含め、残高のすべての変更が self. を付けてそのセッターを通るようにしてください。
提供されたコードは所有者と開始時の残高を読み取り、その後、+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
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rubyオンラインコンパイラ