昔の自分に説明したいこと(2021/03/12 追記)
selfってなに?
オブジェクト自身のこと
オブジェクト指向ってなんだったんだっけ?
「オブジェクトとの対話」ということ
オブジェクトにメッセージとしてメソッドを呼びかけてあげるから、オブジェクトが返事をしてくれる
その対話がオブジェクト指向
「オレは1970年代に誰よりも先にオブジェクト指向を勉強した!」
と豪語する、銭湯で出会ったプログラマのおじさまに、↑こう言い切っていいか聞いたら「OK」と言われています。
いつもオブジェクトと対話してるじゃん
"Hello" + "World"
# => "HelloWorld"
"Hello"という文字列は、Stringのインスタンスオブジェクト
"Hello"というオブジェクトに対して、"+"というメソッドをメッセージとして呼びかけてあげるから返事をしてくれている。
冗長に書けばこういうこと。
String.new("Hello").+(String.new("World"))
メソッドは全部オブジェクトに対するメッセージなんだぜ
そしてメッセージを呼びかける主語は、君だ。
オブジェクト指向って、なんかコードをオブジェクトと見立てて
オブジェクトを主語として動詞を生やして、そいつが生き生きと動くみたいな感じにするのがオブジェクト指向だと思っていたな。
文型でいう、SVのSがオブジェクトだと思ってた。
でもSはオレ。だから、文型はSVOになって、Sがオレで、VはO(オブジェクト)に対する他動詞みたいなイメージ。
だから、
# オイ、"Hello"。 オマエこの"World"と合体しろ!
String.new("Hello").+(String.new("World"))
「クラスとインスタンス」 --> 「クラスオブジェクトとインスタンスオブジェクト」
クラスとインスタンス。
インスタンスはクラスという設計図を元に生成されたオブジェクト。
だからクラスはオブジェクトじゃない、と思っていたな。
でもRubyの世界では、クラスもオブジェクトだからな。
クラスはClassクラスっていうクラスのインスタンス。
だから、クラスとインスタンスという言葉はもうやめて、
「クラスオブジェクトとインスタンスオブジェクト」と呼ぶことにしよう。
クラスオブジェクトに話しかけてみる
オイ、Stringクラス。お前クラスオブジェクトらしいな。
アンタのクラスはClassなんだって?
String.class
# => Class
オイ、Classクラスオブジェクト、アンタのクラスはなんなんだ一体
Class.class
# => Class
ナンカ、タノシクナッテキタ
Class.class.class.class.class.class.class
# => Class
(再) selfってなに?
以上のことを踏まえて、selfってなに?という質問に対して、このように答えたい。
話しかけられてるヤツ(オブジェクト)
話しかけられてるヤツは誰だ?
class Omae
def self.dare?
self
end
def dare?
self
end
end
Omae.dare? == Omae
# => true
ore = Omae.new
ore.dare? == ore
# => true
こうやってみると、自明だね。
暗黙的なself
レシーバを指定しなければ、いつでもレシーバはself。
だから明示的に書かなくても、暗黙的にselfが決まる。
selfがいつでもそこにいること。メッセージを呼びかけられてる相手はいつもいることを知って欲しい。
例
class Omae
attr_reader :hair
def initialize(hair = nil)
@hair = hair
end
def hage?
hair.nil?
end
end
ore = Omae.new("wwwwwwwwwwwwwwww")
ore.hage?
# => false
Omae#hage?の中で使っている、hairは、
attr_readerで定義されている、インスタンスメソッドのOmae#hairのこと。
なのでOmae#hage?の中でOmae#hairが使えているのは、暗黙的にselfが決まって、呼びかけられるヤツ(ore)がそこにいるから。
だから、self.hairとして明示的にレシーバを指定しなくてもOmae#hairが呼べてる。
暗黙的にselfがそこにいるなら、プライベートメソッドはどうなの?
「self.プライベートメソッドとかやったら怒られるよね!?」
もう一回言います。レシーバを指定しなければ、いつでもレシーバはself。
private_methodは、レシーバを直接指定できないだけ。
class Omae
def dare?
private_dare?
end
private
def private_dare?
self
end
end
ore = Omae.new
ore.dare? == ore
# => true
以上
以下から一年前の僕↓
経緯
selfについて理解するためにオブジェクト、クラス、インスタンスのこれらの用語について自分の中で納得する説明が必要でした。そして、それらの用語を誤解したまま納得し、誤った論理の手続きでselfと紐づけて理解していました(つもりになっていました)。
そこでそれを記事にしてしまった結果、ご丁寧にご指摘いただきましたので、どう誤ったのか、なにが誤りなのかを記録として残しておきます。
selfを理解するために僕がこしらえた誤ったロジックいうのは、簡単に言うと
「 オブジェクトはクラスとインスタンスどちらも指すことができる、だからselfはクラス自身にもなるしインスタンス自身にもなる」
【大正解】 RubyではすべてのクラスはClassという名のクラスのインスタンス
このコメントをいただくまでRubyのオブジェクト指向というものをきちんと理解していませんでした。理解しようともしていなかったことに気づきました(反省)
誤解したまま発信してしまった内容
selfを理解する前に... 「オブジェクト」, 「クラス」, 「インスタンス」これらの用語について
**「クラス」**はオブジェクトを作成するための青写真のようなもの、オブジェクトそのものではなく、そのオブジェクトの仕様書, 設計図のイメージ。
**「インスタンス」は実際にその設計図(クラス)から生成されたオブジェクトであり、どういう動きをさせるか命令することができる、物理的に存在していてるイメージ。
そして「オブジェクト」**は、きちんと定義されていない用語で、クラスともインスタンスとも指すことができる言葉です。
通常、インスタンスと同義ですが、しばしばクラスを指すことがあります。これは文脈で判断されます。
「オブェクト」はクラスとインスタンスどちらとも指すことができ、文脈や背景から判断される用語であるということをふまえて
英語的観点からselfは、Yourself(あなた自身)、Myself(わたし自身)など、 self = 自身, 自己 という意味を持っています。
Rubyではself一単語で「オブジェクト自身」を意味します。
そしてオブジェクトとは、クラスとインスタンスどちらも指すことができる言葉であり、それは文脈や背景からどちらなのかを判断する、
言い換えればselfは、selfが使われる場所によって、「クラス自身」にもなるし「インスタンス自身」にもなるということ。
この使われる場所によって判断する例として以下が挙げられます。
- クラス内直下ではそのクラス自身を指す
- インスタンスメソッド内ではそのクラスから生成されるインスタンス自身を指す
- インスタンスメソッド内であっても、self.classという記述でそのクラス自身を指す
- クラスメソッド内ではそのクラス自身を指す
class Blog
def foo # インスタンスメソッド
end
def self.foo # クラスメソッド(このselfはクラス自身(Blog)を指す)
end
def bar # インスタンスメソッド
self.foo # インスタンスメソッドのfooが呼ばれる(このselfはインスタンス自身(Blog.new)を指す)
foo # インスタンスメソッドのfooが呼ばれる
self.class.foo # クラスメソッドのfooが呼ばれる(このような記述でインスタンスメソッド内でもクラス自身を指すことができる)
end
def self.bar # クラスメソッド(このselfはクラス自身を指す)
self.foo #クラスメソッドのfooが呼ばれる
foo #クラスメソッドのfooが呼ばれる
end
end
オブジェクトはloose term ?
Rubyのオブジェクト指向についてまずきちんと理解することを怠ったことが誤解の主な原因でしたが、オブジェクト、クラス、インスタンスの意味について以下を参考にしたことも要因のひとつです。
What is the difference between class, object, and instance in simple terms?
A class is like a blueprint for an object. It isn’t the object itself, just its specification.
An instance is an actual object built from the blueprint. It has a physical presence in memory and can be called upon to do work.
‘object’ is a loose term that can mean class or instance depending on context, but typically means an instance. But often developers use ‘object’ to mean class at times, and that’s usually understood.
要は self => オブジェクト自身 以上!
selfはオブジェクトを指します。 オブジェクトには、クラス、インスタンスがあります。
この一文で全て完結!
ただ、このシンプルなセンテンスで納得するまで初学者はいろんなつまづきがあるんだなあと実感するとともに、アウトプットすることによって書籍では出会えない生の言葉でそれを正してくれる機会に巡り会うことができるので、本当によかったなあと思いました。
ありがとうございました!