記事の対象
selfって何?
クラスメソッドって?
classやインスタンスはなんとなくわかる
この記事で解説すること
- selfとは
- オブジェクトとは
- いろいろな場所でのself(クラス内・クラス外・インスタンスメソッド内・クラスメソッド内など)
selfの一般的な説明
selfはオブジェクトそのものである
と言われてもピンとこなかったんですよね。
ただ、腑に落ちた今は確かにそのとおりだなと思います。
オブジェクトとは
まずオブジェクトについて理解していきましょう。
Rubyは全てがオブジェクトです。
- 文字列オブジェクト
- 数値オブジェクト
- 配列オブジェクト
- ハッシュオブジェクトなど
現実世界で言えば人やモノ、動物などありとあらゆるものをオブジェクトとして扱います。
オブジェクトとインスタンスの違い
オブジェクトとインスタンスの違いは下記サイトでわかりやすく説明されていたので気になる方は読んでみてください。
一言で言うと
クラスから生成されたオブジェクトのことをインスタンスと呼ぶ
です。
クラス・インスタンス・オブジェクトの違いは神の気分になるとわかる
インスタンスの生成
クラス名.new
class Sample
end
p Sample.new #=> #<Sample:0x00007fe79b835240>
インスタンスが生成できました。
selfについて
ここまではインスタンスやオブジェクトについてでしたが、ついにselfに片足を突っ込みます。
とりあえず適当にrbファイルを作って実行してみましょう。
もしくはターミナルでirbと打った後selfと打ってみましょう。
(Rubyをインストールしていないと使えません。ruby -vと打ってバージョン情報が出ないようならインストールされていないのでインストールしてください。)
p self
#=> main
mainというものが出てきました。
mainとはなんでしょうか?
一言で言うと
mainとはトップレベルに存在するインスタンスのことでObjectクラスのインスタンスです。
難しいですね。
しっかり解説していきます。まずはObjectクラスからです。
Objectクラス
Objectクラスとはクラスの実質的頂点(親)にいるクラスです。(実際にはもう一つ上のクラスが存在しますが、ここでは割愛します。)
クラスは階層構造になっていて文字列クラスなどの親クラスがObjectクラスになります。
(classメソッドで自身のクラス、superclassメソッドで親クラスを取得することができます。)
p "文字列".class #=> String
p String.superclass #=> Object
トップレベル
次にトップレベルですが、これはclass定義やmodule定義の外側のことを言います。
(moduleについては本記事では解説しません。制限が加わったclassのようなものと思っておいてください。)
# ここから
#
#
#
# ここまでがトップレベル
class Sample
# クラス内
end
# ここから
#
#
#
# ここまでもトップレベル
module SampleModule
# モジュール内
end
# ここから
#
#
#
# ここまでもトップレベル
そしてターミナルでirbと打った時にいるのもトップレベルです。
ターミナルでirbと打つと
irb(main):001:0>
となります。
ここがトップレベルであり、そしてirbの後にmainとあることが確認できると思います。
またトップレベルでselfのクラスを確認してみると
p self #=> main
p self.class #=> Object
トップレベルのself(main)のクラスはObjectだということがわかります。
先ほどの発言に戻ると
mainとはトップレベルに存在するインスタンスのことでObjectクラスのインスタンスです。
でした。
これは
トップレベルでのpメソッドの実行結果はp self #=> main
だったこと。
そしてp self.class #=> Object
だったこと
そしてselfとはオブジェクト自身(インスタンス自身)を指すこと。
からもわかります。
トップレベルでいきなりpメソッドなどを実行できるのはmainがObjectクラスのインスタンスだからなんですね!
(ObjectクラスにはKernelモジュールがインクルードされているので実行できるというのが正確な答えだがここでは割愛)
クラス内のself
次にクラス内のselfをみていきます。
class Sample
p self #=> Sample
end
selfはオブジェクト自身のことでした。そのためクラス内ではそのクラスオブジェクト自身を表しています。
インスタンスメソッド内のself
インスタンスメソッド内のselfはインスタンス自身(オブジェクト自身)を表しています。
class Sample
def hoge
p self
end
end
sample = Sample.new
sample.hoge #=> #<Sample:0x00007f8524034f70>
ちなみにRubyはメソッドを呼び出す時、暗黙的にselfに対してメソッドを呼び出しています。(勝手にselfに対してメソッドを呼び出す。)
どういうことかというと
class Person
def greeting
p self
hello
end
def hello
p "hello"
end
end
person = Person.new
person.greeting #=> #<Person:0x00007f9937848a28>
#=> "hello"
これと同じものが以下になります。
class Person
def greeting
p self
self.hello
end
def hello
p "hello"
end
end
person = Person.new
person.greeting #=> #<Person:0x00007f9937848a28>
#=> "hello"
どこが違うかお気づきでしょうか?
そうです。greetingメソッド内のhelloの呼び出しの前にself.がついています。
実はこのself.は付けても付けなくても同じ動きになるのです。
メソッドの呼び出しのたびにselfをつけるのは大変なのでこの仕様になっているのだと思います。
この時のgreetingメソッド内のselfはPersonクラスのインスタンス自身ですのでそのインスタンスに対してhelloメソッドが呼ばれているんですね。
(greetingメソッド内のself.hello
とトップレベルのperson.hello
は同じ結果になる。)
クラスメソッドのself
クラスメソッド内のselfもオブジェクト自身を表しています。
class Person
def self.greeting
p self
end
end
Person.greeting #=> Person
Personが返されています。
もちろんこのメソッド定義部分のselfもオブジェクト自身を表しているのですがメソッドの定義場所にあるselfってちょっと不思議な感じですよね。
def self.greeting # ← このself
end
クラスメソッドとは特異メソッドの一つです。
では特異メソッドとは何か?
特異メソッド
特異メソッドはクラスとは関係なく個々のオブジェクト(インスタンス)に対してメソッドを定義します。
morning = "good morning"
def morning.greeting
p self
end
morning.greeting #=> "good morning"
これは何が起こっているのでしょうか?
まずmorning = "good morning"
でmorningという変数(オブジェクト)に"good morning"という文字列を代入しています。
その後morningオブジェクトに対してgreetingメソッドを定義しています。
greetingメソッド内ではpメソッドでselfを返しています。
この場合のselfは"good morning"という文字列オブジェクトなので
"good mornig"という文字列が出力されます。
この形が特異メソッドです。
クラスメソッド定義方法と同じですね。
class Person
def self.greeting
end
end
上のコードと見比べるとdef 〇〇.メソッド名のように定義方法が一緒ですね。
そしてこの時のselfはPersonだったので
class Person
def Person.greeting
end
end
このようにも書けます。
最後に
いろいろなところでselfを使ってみました。
selfがオブジェクト自信を表すということが理解できれば幸いです。
やはり自分でコードを動かして検証していくと理解が高まりますね。
何かお気づきのことがありましたらコメント欄で教えていただけると助かります。