- 作者: Nicholas C. Zakas,和田祐一郎
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/06/18
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
JavaScript では以下のように書けます。
var person = { name : "Matsumoto", sayName : function () { console.log(this.name); } }; person.sayName(); //=>"Matsumoto"
これは JavaScript では自然ですが、Ruby で同等のことは可能でしょうか。いわゆる「特異メソッド」を使ってみます。
person = Object.new def person.name "Matsumoto" end def person.sayName puts self.name end person.sayName #=>"Matsumoto"
似たようなことは一応可能ですね。
では次の JavaScript コードはどうでしょう。
function sayNameForAll() { console.log(this.name) } var person1 = { name : "Matsumoto", sayName : sayNameForAll }; var person2 = { name : "Larry", sayName : sayNameForAll }; var name = "van Rossum"; person1.sayName(); //=>"Matsumoto" person2.sayName(); //=>"Larry" sayNameForAll(); //=>"van Rossum"
これは Ruby なら
def sayNameForAll puts self.name end person1 = Object.new def person1.name "Matsumoto" end def person1.sayName sayNameForAll end person2 = person1.clone def person2.name "Larry" end def person2.sayName sayNameForAll end def self.name "van Rossum" end person1.sayName #=>"Matsumoto" person2.sayName #=>"Larry" sayNameForAll #=>"van Rossum"
で、これもだいたい JavaScript と似たようなことが出来ていますね。
しかしこれなら、もうクラスベースで、
class Person def initialize(name) @name = name end def sayName puts @name end end person1 = Person.new("Matsumoto") person2 = Person.new("Larry") person1.sayName #=>"Matsumoto" person2.sayName #=>"Larry"
とやりたくなるのですけれど。プロトタイプベースのいいところって何だろう。ああ、そうか、特定のインスタンスに
def person1.virtue "gentleman" end puts person1.virtue #=>"gentleman"
こういうことができることか。Ruby では Python みたいにいきなり person1.virtue = "gentleman"
という書き方はできないのだけれど、これは意図的なんだろうな。もちろん、さらに
class Person attr_accessor :virtue end person1.virtue = "gentleman" person2.virtue = "interesting" puts person1.virtue #=>"gentleman" puts person2.virtue #=>"interesting"
ということはできる。またさらに
class Person def putout puts @virtue end end person1.putout #=>"gentleman"
なので、インスタンス変数を明示的に使う前にアクセサを宣言してもよいのだな。