0
0

More than 1 year has passed since last update.

class<<selfという書き方は?

Posted at

ruby書いているとタイトルのような記述を見たことがある人は多いとおもいます。自分はよくわからなかったので今回の記事でまとめてみようとおもいます。

こういう時はとりあえず公式ドキュメントを見てみようと思ったので見てみました。すると、

特異クラス方式。複数のメソッドを一度に定義するとき向き
https://docs.ruby-lang.org/ja/3.0/doc/spec=2fdef.html#class_method

特異メソッドとは?

特異メソッドとは1つのオブジェクトに対して適用されるメソッドのことです。実際に例を見ていきましょう

class User
  def my_name
    puts "自己紹介しましょう"
  end
end

ouki = User.new
riboku = User.new

def ouki.introduction
  p "秦国最強の将軍である"
end

ouki.my_name
=> 自己紹介しましょう

riboku.my_name
=> 自己紹介しましょう

ouki.introduction
=> "秦国最強の将軍である"

riboku.introduction
NoMethodError (undefined method `introduction' for #<User:0x000002364158c3b0>)

rubyではメソッドは、def メソッド名 endと記述します。
my_nameはインスタンスメソッドです。そのため、Userクラスから作成されたoukiインスタンスやribokuインスタンスではmy_nameメソッドが使えます。
しかし、ouki.introductionメソッドは違います。これは、oukiインスタンスしか使えないメソッドなんです。そのため、ribokuインスタンスがそのメソッドを使うとしてもエラーを吐くわけです。

あるオブジェクトにのみ適用できる特別に異なるメソッド、それが特異メソッドです。

特異メソッドの実態

rubyの原則として、メソッドはクラスに紐づくというものがあります。そのため特異メソッドもなんかしらのクラスに属しているはずなんですね。実際にどこのクラスに属しているのかを見ていきましょう。

class User
  def my_name
    puts "自己紹介しましょう"
  end
end

ouki = User.new
riboku = User.new

def ouki.introduction
  p "秦国最強の将軍である"
end

p ouki.class.method_defined?(:introduction)
=> false
p ouki.singleton_class.method_defined? :introduction
=> true

上記からも分かるように、ouki.introductionメソッドという特異メソッドは、Userクラスに属しているのではなく、特異クラスに属していることが分かります。なお、特異クラスは特異メソッドが定義されたときに自動で作成されます。

つまり、特異クラスに特異メソッドは属しているということです。

クラスに特異メソッドを定義してみましょう

class User
  def User.introduction(name)
    p "#{name}"
  end
end

puts User.introduction("王騎")
=> 王騎

このintroductionメソッドの呼び出し方は、クラスメソッドの呼び出し方と同じなんです。つまり、

class User
  def self.introduction(name)
    p "#{name}"
  end

  puts self.introduction('王騎')
end

これと同じなんです。
ここからわかることは、クラスメソッドはクラスの特異メソッドにあたるんです。

class<<selfとは?

これは特異クラス定義式といいまして、そのまんまの意味です。特異クラスを定義するものです。ここまで読んだ方であれば、特異クラスとは特異メソッドを定義した時にでてくるものでしたね。
実際に特異クラス定義式で書いてみましょう

class User; end
class << User
  def production(name)
    puts "#{name}"
  end
end

puts User.production('王騎')
=> 王騎

class << UserでUserの特異クラスに対して、Userの特異メソッドを定義しています。
さらにUserの部分をselfに変えてあげれば、

class User; end
class << self
  def production(name)
    puts "#{name}"
  end
end

puts User.production('王騎')
=> 王騎

今回のタイトルの形ができましたね。

まとめると、class << selfは特異クラスにたいして特異メソッドを定義しているんです。

以上です。何か間違いがございましたら、ご教示いただけますと幸いです。

【参考資料】

0
0
1

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