Closed yoshimitsu41 closed 5 years ago
説明しづらいのでcode1,code2という名前をつけました
code1についてはインスタンスメソッドを定義しているからですね def hello
というやつです。
code2のattr_reader
はreadのアクセサメソッドを定義するメソッドなので実体としては下記と同じです。簡潔に記述できるというメリットがあります。
class Product
def initialize(name, price)
@name = name
@price = price
end
def name
@name
end
def price
@price
end
end
@yoshimitsu41 追加で疑問があればコメントお願いします:bow:
なるほど。 本では読んだのですがなんとなく附に落ちました。
code1はhelloというインスタンスメソッドを呼び出してその結果を表示させているだけなので、アクセサメソッドは不要。
code2は
product = Product.new('pen',100)
でproductにインスタンスを代入していて
そのインスタンスに外部から読み込もうとするとアクセサメソッドが定義されてないとエラーを起こすということですね。
ありがとうございました。
code1はhelloというインスタンスメソッドを呼び出してその結果を表示させているだけなので、アクセサメソッドは不要。
表現の問題かもですがちょっと解釈が違うようです。code1は@nameというインスタンス変数を直接参照して取得しているのでアクセサメソッド不要です。
code2は product = Product.new('pen',100) でproductにインスタンスを代入していて そのインスタンスに外部から読み込もうとするとアクセサメソッドが定義されてないとエラーを起こすということですね。
も正確にはインスタンスのインスタンス変数を参照するためにアクセサメソッドを定義しています。
code1,code2で文字列を出力しようとしていたりしていなかったりするのでわかりづらいかもですが
[27] pry(main)> class Product
[27] pry(main)* def initialize(name)
[27] pry(main)* @name = name
[27] pry(main)* end
[27] pry(main)* end
=> :initialize
[28] pry(main)>
[29] pry(main)> Product.new("ruby").name
NoMethodError: undefined method `name' for #<Product:0x00007fe7df0dee80 @name="ruby">
from (pry):46:in `__pry__'
[30] pry(main)>
[31] pry(main)> class Product2
[31] pry(main)* attr_reader :name
[31] pry(main)*
[31] pry(main)* def initialize(name)
[31] pry(main)* @name = name
[31] pry(main)* end
[31] pry(main)* end
=> :initialize
[32] pry(main)>
[33] pry(main)> Product2.new("ruby").name
=> "ruby"
[34] pry(main)>
[35] pry(main)> class Product3
[35] pry(main)* def initialize(name)
[35] pry(main)* @name = name
[35] pry(main)* end
[35] pry(main)*
[35] pry(main)* def name
[35] pry(main)* @name
[35] pry(main)* end
[35] pry(main)* end
=> :name
[36] pry(main)>
[37] pry(main)> Product3.new("ruby").name
=> "ruby"
実装の違いを書いてみると上記のようになりProduct2,3は同義ですがアクセサメソッドを定義することで簡潔に書けるメリットがあります。あとはインスタンス変数を直接参照しないのでインスタンス変数が変更されていないことがわかりやすく保守性が上がったりします。
ちょっと極点な例ですが下記のようにアクセサメソッドのゲッターメソッドだけにしておけばインスタンス変数の破壊的な変更が行われないのでコードとしての品質が上がるみたいなことがあります
[39] pry(main)> class Car
[39] pry(main)* attr_reader :tire_count
[39] pry(main)*
[39] pry(main)* def initialize
[39] pry(main)* @tire_count = 4
[39] pry(main)* end
[39] pry(main)* end
=> :initialize
[40] pry(main)>
[41] pry(main)> Car.new.tire_count
=> 4
[42] pry(main)>
[43] pry(main)> class Car
[43] pry(main)* def initialize
[43] pry(main)* @tire_count = 4
[43] pry(main)* end
[43] pry(main)*
[43] pry(main)* def tire_count
[43] pry(main)* @tire_count = @tire_count + 1
[43] pry(main)* @tire_count
[43] pry(main)* end
[43] pry(main)* end
=> :tire_count
[44] pry(main)>
[45] pry(main)> Car.new.tire_count
=> 5
@yoshimitsu41 コメント追記しました:bow:
確かにわかったつもりでしたが、解釈が違っていました。 ようやくわかりました! 丁寧なご説明ありがとうございます。
良かったです!:+1:
概要
attr_accessor attr_reader attr_writer の必要な時と不要なときに関して。
困っていること(理解できてないこと)
code1
code2
このアクセサメソッドが必要な場合と不要な場合の違いはなにでしょうか?
よろしくお願いいたします。