1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

インスタンス変数・ゲッターセッター・アクセスメソッド

今回はインスタンス変数、インスタンスメソッド、ゲッターとセッター、attr_accessorについて書きます

今回のコード

class MarsAlien
  #attr_reader :name →ゲッターの役割
  #attr_writer :name →セッターの役割
  attr_accessor :name #ゲッター・セッターの役割

  def initialize(name) #初期化メソッド
    @name = name  #@nameはインスタンス変数
  end

  def greet #インスタンスメソッド
    puts '#{@name} says hello to earth'
  end
end

mars_bob = MarsAlien.new('Bob')
mars_erich = MarsAlien.new('Erich')

mars_bob.greet #=> Bob says hello to earth

mars_bob.name #=> "Bob"
mars_bob.name = "Johnny" #=> "Johnny"

前回の復習

ざっくりと、前回の確認をします。

・クラス:〇〇製造工場
・インスタンス:工場で作られた固有の〇〇(オブジェクト、物体)
・メソッド:クラスやインスタンスが行える「動作・機能」
initializeメソッド:作成されたインスタンスに、初期値(例:名前など)を設定する

インスタンス変数

では、前回の最後で登場した「インスタンス変数」(例:@name)とは何でしょうか?

インスタンス変数とは、個々のインスタンス毎に特有のデータ(例:名前、年齢)を保持するための変数です。
(別の言い方をすると、インスタンス間で共有しないデータのためのものです)

以下のように、@変数名と記述します。

class MarsAlien
  def initialize(name)
    @name = name #インスタンス変数
  end
end

mars_bob = MarsAlien.new('Bob')
mars_erich = MarsAlien.new('Erich')

上記の例を見てみましょう。火星人クラス(MarsAlien)から作成された、火星人ボブ(mars_bob)や火星人エリック(mars_erich)は、それぞれインスタンスです。そこで、彼らが(共有せず)固有に持っている名前を、初期値としてインスタンス変数で設定します。

また、@から始まるインスタンス変数は、同じクラス内であれば、メソッドを超えて参照することができます。その意味を次の節で見てみましょう。

インスタンスメソッド

インスタンスメソッドとは、その名の通り、固有のインスタンスにのみ使用可能なメソッドです。

クラスが〇〇製造工場であることを思い出してみましょう。「挨拶をする」というメソッド(動作)があったさい、その主体者は、工場(クラス)ではなく、個々のオブジェクト(インスタンス)です。インスタンスメソッドは、そういった個々のオブジェクトが出来る動作を記述しています。

そのため、インスタンスメソッドを使用するためには、newメソッドでインスタンスを作成する必要があります。


class MarsAlien
  def initialize(name) #初期化メソッド
    @name = name  #@nameはインスタンス変数
  end

  def greet #インスタンスメソッド
    puts '#{@name} says hello to earth' #@nameを参照している
  end
end

mars_bob = MarsAlien.new('Bob')
mars_erich = MarsAlien.new('Erich')

mars_bob.greet #=> Bob says hello to earth 
mars_erich.greet #=> Erich says hello to earth

最後の2行で、ボブとエリック(火星人クラスのインスタンス)に、インスタンスメソッドであるgreetメソッドを使用して、地球に挨拶させています。
また、@name(インスタンス変数)を利用することで、メソッドをまたいで参照が可能になっています。

ゲッターとは

ちなみに、@で定義したインスタンス変数が知りたい場合は、どうすればよいのでしょうか?実は、作成したインスタンスから直接参照しようとすると、下記のようなエラーになってしまいます。

class MarsAlien
  def initialize(name) 
    @name = name  #@nameはインスタンス変数
  end
end

mars_bob = MarsAlien.new('Bob')
mars_bob.name #=>undefined method `name'エラーとなり、参照できない

これは、インスタンス変数の値が、クラス内の範囲でしか参照できないためです。
そのため、クラス外からインスタンス変数を参照したい場合は、下記のように、ゲッター、つまり、クラス外からインスタンス変数を「ゲットする」ためだけのメソッドを定義する必要があります。

class MarsAlien
  def initialize(name) 
    @name = name  #@nameはインスタンス変数
  end

  def name #ゲッター
    @name
  end
end

mars_bob = MarsAlien.new('Bob')
mars_bob.name #=> "Bob"(ゲッターがあるので、参照できるようになった)

とはいえ、インスタンス変数が複数ある場合などは、↑のようにゲッターをいちいち書いていたら、とても手間ですね。なんとかならないでしょうか?

実はなんとかなるのですが、その前に、ゲッターと並んで紹介されることが多い「セッター」の概念についても確認しておきましょう。

セッターとは

ゲッターが(主に)インスタンス変数参照用であるのに対し、「セッター」はインスタンス変数を書き換える(更新する)場合に使用されます。
例を見てみましょう。

class MarsAlien
  def initialize(name) 
    @name = name  #@nameはインスタンス変数
  end
end

mars_bob = MarsAlien.new('Bob')
mars_bob.name = "Johnny" #=>undefined method `name'エラーとなり、"Bob"から"Johnny"へ更新できない

上記でエラーが出ているのは、インスタンス変数をクラス外から更新することはできないためです。そのため、インスタンス変数書き換え用メソッドのセッターを用意します。

class MarsAlien
  def initialize(name) 
    @name = name  #@nameはインスタンス変数
  end

  def name=(name) #セッター
    @name = name
  end
end

mars_bob = MarsAlien.new('Bob')
mars_bob.name = "Johnny"  #=> "Johnny"(セッターがあるので、"Bob"から"Johnny"へ更新できる)

このセッターくんも、ちょっと面倒ですよね。

それでは、セッター・ゲッターの記述を(体感)10倍ほど簡単にしてくれるのがattr_accessor(アクセスメソッド)を見てみましょう!

attr_accessorとは

 attr_accessorは、3種類あるうちのアクセスメソッドのひとつです。ゲッターとセッターの役割を持ち、インスタンス変数の値の参照・更新をともに可能にしてくれます

メソッド 動作
attr_reader :変数名 ゲッターと同じ役割。インスタンス変数の値を参照する
attr_writer :変数名 セッターと同じ役割。インスタンス変数の値を更新する
attr_accessor :変数名 ゲッターとセッター、両方の役割を持つ。インスタンス変数の値が参照でき、かつ更新できる

最後に、attr_accessorの定義方法を確認しましょう。
(ちなみに、:変数名(変数名にコロン)は「シンボル」という構文を使用しています。詳細は、シンボルに関するこちらの記事を参照してください)

class MarsAlien
  #アクセスメソッド(@name変数をクラス外から参照・更新するのを可能にしてくれる)
  attr_accessor :name 

  def initialize(name) 
    @name = name  #@nameはインスタンス変数
  end
end

mars_bob = MarsAlien.new('Bob')

mars_bob.name 
#=> "Bob"(attr_accessorがあるので、クラス外から値が参照できる)

mars_bob.name = "Johnny"  
#=> "Johnny"(attr_accessorがあるので、クラス外から値が更新できる)

参考記事

(英語)クラスメソッドとインスタンスメソッドについて
クラス変数とインスタンス変数について
Rubyリファレンスマニュアル(変数と定数)

おつかれさまでした!

お付き合いくださり、ありがとうございました!!

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
1
Help us understand the problem. What are the problem?