LoginSignup
50
44

More than 3 years have passed since last update.

Rubyのselfってなんだ?

Last updated at Posted at 2020-05-17

記事の対象

selfって何?
クラスメソッドって?
classやインスタンスはなんとなくわかる

この記事で解説すること

  • selfとは
  • オブジェクトとは
  • いろいろな場所でのself(クラス内・クラス外・インスタンスメソッド内・クラスメソッド内など)

selfの一般的な説明

selfはオブジェクトそのものである

と言われてもピンとこなかったんですよね。
ただ、腑に落ちた今は確かにそのとおりだなと思います。

オブジェクトとは

まずオブジェクトについて理解していきましょう。
Rubyは全てがオブジェクトです。

  • 文字列オブジェクト
  • 数値オブジェクト
  • 配列オブジェクト
  • ハッシュオブジェクトなど

現実世界で言えば人やモノ、動物などありとあらゆるものをオブジェクトとして扱います。

オブジェクトとインスタンスの違い

オブジェクトとインスタンスの違いは下記サイトでわかりやすく説明されていたので気になる方は読んでみてください。
一言で言うと
クラスから生成されたオブジェクトのことをインスタンスと呼ぶ
です。

クラス・インスタンス・オブジェクトの違いは神の気分になるとわかる

インスタンスの生成

クラス名.new

インスタンスの生成
class Sample
end

p Sample.new #=> #<Sample:0x00007fe79b835240>

インスタンスが生成できました。

selfについて

ここまではインスタンスやオブジェクトについてでしたが、ついにselfに片足を突っ込みます。
とりあえず適当にrbファイルを作って実行してみましょう。
もしくはターミナルでirbと打った後selfと打ってみましょう。
(Rubyをインストールしていないと使えません。ruby -vと打ってバージョン情報が出ないようならインストールされていないのでインストールしてください。)

sample.rb
  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をみていきます。

クラス内のself
class Sample
  p self #=> Sample
end

selfはオブジェクト自身のことでした。そのためクラス内ではそのクラスオブジェクト自身を表しています。

インスタンスメソッド内の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もオブジェクト自身を表しています。

クラスメソッド内の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がオブジェクト自信を表すということが理解できれば幸いです。

やはり自分でコードを動かして検証していくと理解が高まりますね。
何かお気づきのことがありましたらコメント欄で教えていただけると助かります。

参考

るびま
http://i.loveruby.net/ja/rhg/book/minimum.html

50
44
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
50
44