オブジェクトについて
オブジェクトとは
Rubyにおいてはクラスから生成されたもののこと。
クラスについて
Hogeクラス、のようなクラスを定義したとする。RubyではこのクラスもClassクラスに所属しているオブジェクトである、というのが大きなスタート。
これはどういうことかと言うと、HogeクラスというものがあったとするとこのHogeクラスも実際はClass.new
して作られている、オブジェクトである、ということ。
下記の意味はHoge=Class.new
と同意義である。
class Hoge
end
インスタンスオブジェクト(インスタンス)
クラスから生成されるのがインスタンスオブジェクト(インスタンス)。
クラス名.new
で生成することができる。
RailsにおけるモデルはClassクラスからインスタンスを生成し、定数を与えていると言える。
コントローラーも同様。
レシーバーとは
メソッドの戻り値を受ける対象
下記の場合、Personがレシーバー。オブジェクトの世界ではオブジェクトにメッセージを送り、オブジェクトがメッセージを受け取る、と捉える。
メソッド呼び出しに関する概念でメソッドを呼び出す対象のオブジェクトのこと。←(@scivola様ご指摘ありがとうございます。)
具体例
person = Person.new('たろう')
の部分においてはPerson クラスがレシーバー。
person.put_receiver
の部分においてはローカル変数 person に代入されている Personオブジェクトがレシーバー。←(@scivola様ご指摘ありがとうございます。)
class Person
attr_accessor :name
def initialize(name)
@name = name
end
def greeting
"私の名前は#{@name}です。"
end
def put_receiver
puts self
# selfでレシーバーを取得。言い換えれば、インスタンスメソッドの呼び出し元のオブジェクトを取得する
# Pesrsonインスタンスオブジェクト自身を返す
puts self.name
# レシーバーのnameを取得
# インスタンスオブジェクトに与えられたnameが返る
end
end
person = Person.new('たろう')
person.put_receiver
出力結果
#<Person:0x00007fbae3908f08>
たろう
メソッドの種類について
クラスメソッド
そのクラス自身に関する情報の変更や参照の役割を持つ。
self.xxx
で定義される。クラス名.new
して生成したインスタンスからは呼び出せず、クラスオブジェクトからのみ呼び出せる。
class Hoge
def self.hoge
puts "hoge"
end
end
Hoge.hoge
# => hoge
クラスメソッドの使い所
例えば、5人分のPersonインスタンスを一気に生成するメソッドを定義したいとき、それはPersonクラスのクラスメソッドとして定義するのが適切。インスタンスメソッドとして定義してしまうと、個別のPersonインスタンスから他のPersonインスタンスを生成することになり不適切。
具体例
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def self.bulk_create(data)
data.map { |d| Person.new(d[:name], d[:age]) }
end
end
data = [
{name: '太郎1', age: 10},
{name: '太郎2', age: 20},
{name: '太郎3', age: 30},
{name: '太郎4', age: 40},
{name: '太郎5', age: 50}
]
puts Person.bulk_create(data)
インスタンスメソッド
個別に生成されたインスタンスに関する情報の変更や参照の役割を持つ。
クラスから生成されたインスタンスオブジェクトからしか呼び出せない。
class Hoge
def hoge
puts "hoge"
end
end
Hoge.new.hoge # => hoge
変数の種類について
インスタンス変数
インスタンスごとに独立して持つ変数。変数の前に@
をつけて定義する。
インスタンス変数にアクセスできるのはinitializeメソッドとインスタンスメソッドだけ。
initializeメソッドで初期化されて、その後各インスタンスメソッドから参照、変更される使い方が多い。
class Foo
# initializeメソッドで定義しinitializeメソッドからアクセスできる。
def initialize
@name = '太郎'
p "#{@name} です"
end
# インスタンスメソッドからもアクセスできる
def xxx
p "#{@name} だぞ"
end
# クラスメソッドからはアクセスできない。
def self.yyy
p @name
end
end
foo = Foo.new
# => '太郎です'
foo.xxx
# => '太郎だぞ'
Foo.yyy
# => nil
クラス変数
そのクラス全てのインスタンスで共有される変数。
変数の前に@@
をつけて定義される。
class Hoge
@@count = 0
def xxx
@@count += 1
p @@count
end
def self.yyy
@@count += 1
p @@count
end
end
hoge = Hoge.new
# 同じインスタンス内で値は共有される
hoge.xxx # => 1
hoge.xxx # => 2
# インスタンスが異なっても、同じクラスなので値は共有されている
hoge2 = Hoge.new
hoge2.xxx # => 3
# クラスメソッドからもアクセスできる。値も共有される。
hoge.yyy # => 4
クラスインスタンス変数
変数名の前に@
をつけて定義する。
※見た目はインスタンス変数と同じだが、定義する場所がクラス定義式内になる。
クラス変数とほぼ同じように使えるが、そのクラスのみでしか参照できない。
クラスメソッドからはアクセス可能。
クラスオブジェクトのインスタンス変数であるためインスタンスメソッドからアクセスすることはできない。
クラス定義式内で定義される(メソッド内で初期化されない)。
class Hoge
@class_instance = 'ハロー'
def self.xxx
p @class_instance
end
def yyy
p @class_instance
end
end
class Foo < Hoge
end
# クラスメソッドからクラスインスタンス変数は参照可能。
Hoge.xxx # => 'ハロー'
# インスタンス変数とみなされるため、インスタンスメソッドからクラスインスタンス変数は参照できない
hoge = Hoge.new
hoge.yyy # => nil
# 継承されたクラスからクラスインスタンス変数は参照できない
Foo.xxx # => nil
参考