Rubyにはインスタンス自身を表すselfキーワード
があります。
...
メソッドの内部で他のメソッドを呼び出す場合は暗黙的にselfをつけてメソッドを呼び出し
ています。そのためselfは省略可能
ですが、明示的にselfを付けてメソッドを呼び出して
も構いません。
irb(main):001* class User
irb(main):002* attr_accessor :name
irb(main):003*
irb(main):004* def initialize(name)
irb(main):005* @name = name
irb(main):006* end
irb(main):007*
irb(main):008* def hello
irb(main):009* "Hello, I am #{name}."
irb(main):010* end
irb(main):011*
irb(main):012* def hi
irb(main):013* "Hi, I am #{self.name}."
irb(main):014* end
irb(main):015*
irb(main):016* def my_name
irb(main):017* "My name is #{@name}."
irb(main):018* end
irb(main):019> end
=> :my_name
irb(main):020> user = User.new("Alice")
=> #<User:0x000000010cc2cb28 @name="Alice">
irb(main):021> user.hello
=> "Hello, I am Alice."
irb(main):022> user.hi
=> "Hi, I am Alice."
irb(main):023> user.my_name
=> "My name is Alice."
selfなしでnameメソッドを呼び出す場合
と、self付きで呼びす場合
、それに加えて直接インスタンス変数を参照する場合
の3つのパターンで@nameの内容を参照
- selfがつくとわかりやすい。
- nameだけはローカル変数か
selfの付け忘れで起こる不具合
irb(main):001* class User
irb(main):002* attr_accessor :name
irb(main):003*
irb(main):004* def initialize(name)
irb(main):005* @name = name
irb(main):006* end
irb(main):007*
irb(main):008* def rename_to_bob
irb(main):009* name = 'Bob'
irb(main):010* end
irb(main):011*
irb(main):012* def rename_to_carol
irb(main):013* self.name = 'Carol'
irb(main):014* end
irb(main):015*
irb(main):016* def rename_to_dave
irb(main):017* @name = 'Dave'
irb(main):018* end
irb(main):019> end
=> :rename_to_dave
irb(main):020> user = User.new('Alice')
=> #<User:0x0000000107a9f008 @name="Alice">
irb(main):021> user.rename_to_bob
=> "Bob"
irb(main):022> user.rename_to_carol
=> "Carol"
irb(main):023> user.rename_to_dave
=> "Dave"
irb(main):024> user.name
=> "Dave"
irb(main):025> user.rename_to_carol
=> "Carol"
irb(main):026> user.name
=> "Carol"
irb(main):027> user.rename_to_bob
=> "Bob"
irb(main):028> user
=> #<User:0x0000000107a9f008 @name="Carol">
irb(main):029> user.rename_to_dave
=> "Dave"
irb(main):030> user
=> #<User:0x0000000107a9f008 @name="Dave">
irb(main):031> user.rename_to_bob
=> "Bob"
irb(main):032> user
=> #<User:0x0000000107a9f008 @name="Dave">
name=のような
セッターメソッドを呼び出したい場合は、必ずselfをつける必要
があります。
self.name= 'Bob'のように書けば、ローカル変数とは構文が異なるので確実にname=メソッドを呼び出すことができる
- user.nameがbobと一時的に呼び出されているだけで次userと呼び出すとまた戻っている
クラスメソッドやクラス構文直下のself
irb(main):063* class Foo
irb(main):064* puts "クラス構文の直下のself: #{self}"
irb(main):065*
irb(main):066* def self.bar
irb(main):067* puts "クラスメソッド内のself: #{self}"
irb(main):068* end
irb(main):069*
irb(main):070* def baz
irb(main):071* puts "インスタンスメソッド内のself: #{self}"
irb(main):072* end
irb(main):073> end
クラス構文の直下のself: Foo
=> :baz
irb(main):074> Foo
=> Foo
irb(main):075> Foo.bar
クラスメソッド内のself: Foo
=> nil
irb(main):076> foo = Foo.new
=> #<Foo:0x00000001080dee28>
irb(main):077> foo.baz
インスタンスメソッド内のself: #<Foo:0x00000001080dee28>
=> nil
クラス構文の直下とクラスメソッド内でのselfはFooと表示されます。このFooは「Fooクラス自身」を表しています。
irb(main):001* class Foo
irb(main):002* def self.bar
irb(main):003* self.baz
irb(main):004* end
irb(main):005* def baz
irb(main):006* self.bar
irb(main):007* end
irb(main):008> end
=> :baz
irb(main):009> Foo.bar
(irb):3:in `bar': undefined method `baz' for Foo:Class (NoMethodError)
self.baz
^^^^
Did you mean? bar
from (irb):9:in `<main>'
from
...
irb(main):010> foo = Foo.new
=> #<Foo:0x000000010d056ac8>
irb(main):011> foo.baz
(irb):6:in `baz': undefined method `bar' for #<Foo:0x000000010d056ac8> (NoMethodError)
self.bar
^^^^
Did you mean? baz
...
クラスメソッドからインスタンスメソッドを呼び出す
、インスタンスメソッドからクラスメソッドを呼び出す
とエラーになる
クラス構文直下でクラスメソッドを呼び出せる
irb(main):001* class Foo
irb(main):002* def self.bar
irb(main):003* puts 'hello'
irb(main):004* end
irb(main):005*
irb(main):006* self.bar
irb(main):007> end
hello
=> nil
クラス構文の直下ではクラスメソッドを呼び出すことができます。なぜなら、selfがどちらも「クラス自身」になるからです。
クラスメソッドからインスタンスメソッドで呼び出せる
irb(main):009* class Product
irb(main):010* attr_reader :name, :price
irb(main):011*
irb(main):012* def initialize(name, price)
irb(main):013* @name = name
irb(main):014* @price = price
irb(main):015* end
irb(main):016* def self.format_price(price)
irb(main):017* "#{price}円"
irb(main):018* end
irb(main):019* def to_s
irb(main):020* formatted_price = Product.format_price(price)
irb(main):021* "name: #{name}, price: #{formatted_price}"
irb(main):022* end
irb(main):023> end
=> :to_s
irb(main):024> product = Product.new("A great movie", 1000)
=> #<Product:0x000000010870f018 @name="A great movie", @price=1000>
irb(main):025> product.to_s
=> "name: A great movie, price: 1000円"
クラス名.メソッド
と書く代わりに、self.class.メソッド
のように書く場合もあります。
irb(main):026* class Product2
irb(main):027* attr_reader :name, :price
irb(main):028*
irb(main):029* def initialize(name, price)
irb(main):030* @name = name
irb(main):031* @price = price
irb(main):032* end
irb(main):033* def self.format_price(price)
irb(main):034* "#{price}円"
irb(main):035* end
irb(main):036* def to_s
irb(main):037* formatted_price = self.class.format_price(price)
irb(main):038* "name: #{name}, price: #{formatted_price}"
irb(main):039* end
irb(main):040> end
=> :to_s
irb(main):041> product = Product2.new("A great movie", 1000)
=> #<Product2:0x0000000104c35348 @name="A great movie", @price=1000>
irb(main):042> product.to_s
=> "name: A great movie, price: 1000円"
感想
selfを使ってこなかった理解していなかったのでこれから読んで理解できそうだ。