Help us understand the problem. What is going on with this article?

5分でわかる!クラスメソッドとインスタンスメソッドの違い

More than 1 year has passed since last update.

目的

Rubyを勉強し始めた時につまずきそうなところ
その中でも
・クラスメソッドとインスタンスメソッドの違いについて
・attr_accessorとは
この2つをまとめました。

目次

・クラスメソッドとインスタンスメソッド
・attr_accessor

クラスメソッドとインスタンスメソッド

Rubyでは、以下のようにすることでメソッドを定義することができます。

sample.rb
def number(a,b,c)
    puts a + b + c
end
number(1,2,3)
# 出力結果 => 6

通常、メソッドは以下のようにクラスの中に定義しますが、このままだとエラーになります。
クラスにメソッドを作成すると、それがインスタンスメソッドとなります。
そのため、numberはクラスに含まれたインスタンスメソッドになり、外から使用できなくなります。

sample.rb
class Add
    def number(a,b,c)
        puts a + b + c
    end
end
number(1,2,3)
# 出力結果 => エラー

回避方法1
selfをつけてクラスメソッドにすることで外から使用できるようにする

sample.rb
class Num
    def self.number(a,b,c)
        puts a + b + c
    end
end
Num.number(1,2,3)
# 出力結果 => 6

回避方法2
numberはインスタンスメソッドのため、インスタンスを作成しメソッドを呼び出す

sample.rb
class Num
    def number(a,b,c)
        puts a + b + c
    end
end
num = Num.new
num.number(1,2,3)
# またはNum.new.number(1,2,3)でも同じ
# 出力結果 => 6

その他の方法
initializeを使ってみる
以下のようにinitializeメソッドを定義することで、
classがnewされた際に呼び出され、classのデータの初期化処理を行ってくれます。

sample.rb
class Num
    def initialize(a,b,c)
        @result = a + b + c
    end

    def number
        puts @result
    end
end
num = Num.new(1,2,3)
num.number
# 出力結果 => 6

attr_accessorについて

sample.rb
class Person

  def initialize(name)
    @name = name
  end

  def name
    @name
  end

end

person = Person.new("taro")
puts person.name
# 出力結果 => taro

上記のコードでクラスの外からインスタンス変数(@name)を変更,更新したい!
と思って...

sample.rb
class Person

  def initialize(name)
    @name = name
  end

  def name
    @name
  end

end

person = Person.new("taro")
person.name = "jiro" #インスタンス変数の値を更新
puts person.name
# 出力結果 => エラー

インスタンスから直接nameを変えようとしましたが、nameというメソッドはここではゲッターの役割をしているため、値の更新はできないです。
person.@name = "jiro"としても、インスタンス変数には直接アクセスできないのでエラーになります。

値の更新をできるようにするためにはセッターが必要です。
そこで以下のようにセッターを定義すると無事に値が変更できます。
def name=(val) とは、person.name = "jiro"と「name」への代入式を書いた時に呼び出されるメソッドです。

sample.rb
class Person

  def initialize(name)
    @name = name
  end
#セッター↓
  def name=(val)
    @name = val
  end
#ゲッター↓
  def name
    @name
  end

end

person = Person.new("taro")
person.name = "jiro" 
puts person.name
# 実行結果 jiro

そして、ゲッターとセッターの両方の役割を持ったものが「attr_accessor」で、以下のようにすることで先ほどのコードよりも短く書くことができます。

sample.rb
class Person
  attr_accessor :name #追加

  def initialize(name)
    @name = name
  end

end

person = Person.new("taro")
person.name = "jiro" #インスタンス変数の値を上書き
puts person.name
# 実行結果 jiro

これでクラス外からインスタンス変数であるnameを操作できるようになりました。
attr_accessor :(インスタンス変数) とすれば、指定されたインスタンス変数が外からでも変更できるようになります。

疑問点

Q.インスタンス変数の書き方attr_accessor :nameと@nameの違い
A.attr_accessorでシンボルを渡して宣言すると、そのシンボル名のインスタンス変数(@name)を中で生成している。

Q.クラスメソッド・インスタンスメソッド使い分け
A.基本的には、インスタンスメソッドで処理を実現できるか検討する。
外部からデータを取得する処理(外部ファイルからデータを取得し、インスタンスを作成する時など)は、クラスメソッドを使用する。

まとめ

・クラスにメソッドを作成すると、それがインスタンスメソッドとなる
・インスタンスメソッドはインスタンスを作成して使用できる
・セッターとゲッターを使うことで値の参照・更新をすることができる。
・セッターとゲッターの両方の役割を持ったものが「attr_accessor」

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away