0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

selfキーワード

Last updated at Posted at 2024-11-13

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を使ってこなかった理解していなかったのでこれから読んで理解できそうだ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?