プロを目指す人のためのRuby入門・第7章重要ポイントまとめ

「プロを目指す人のためのRuby入門」の第7章を読み終わりました

個人的に重要と判断したポイントをまとめます。

クラス外部からのインスタンス変数の取得

インスタンス変数はクラスの外部から参照、変更ができないため、参照や変更がしたければその為のメソッドを定義する必要があります

class User
  def initialize(name)
    @name = name
  end
  
  #インスタンス変数を参照する
  def name
    @name
  end
  
  #インスタンス変数を変更する
  def name= (value)
    @name = value
  end
end


user = User.new('hiroki')
#nameメソッドを経由してインスタンス変数(ここでは@name)を取得する
user.name #=> "hiroki"

#name=メソッドを経由してインスタンス変数を変更する
user.name = 'Bob'
user.name #=> "Bob"

インスタンス変数の値を読み書きするメソッドのことをアクセサメソッドと呼び、attr_accessorなどで簡単に定義できます

class User
  #@nameを読み書きするメソッドの定義を行っている
  attr_accessor  :name 
 
  #以下省略

end

#また、attr_writerなら書き込み専用、attr_readerなら読み取り専用のメソッドを定義していることを表す
オープンクラス

Rubyのクラスは変更に対してオープンなので、オープンクラスと呼ばれます
定義済みのクラスにメソッドを追加したり、メソッドを上書きすることも可能です

class User
  def initialize(name)
    @name = name
  end
end

user = User.new('hiroki')
user.name #=> NoMethodError

このままだとインスタンス変数の参照ができないので、Userクラスにattr_writerを追加する

class User
  attr_reader :name
end

#後からメソッドが追加できたことがわかる
user.name #=> "hiroki"

インスタンス自身を表すselfキーワード

インスタンス変数の読み取り用メソッドを定義する

class User
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def hello
    #インスタンスメソッド内でselfは省略できる
    "Hello, I am #{name}."  
  end

  def hi
    #self付きでインスタンスメソッドを呼び出す
    "Hi, I am #{self.name}."
  end

  def my_name
    #直接インスタンス変数@nameにアクセスする
    "My name is #{@name}."
  end
end

#いずれの場合でもインスタンス変数を参照できる
user = User.new('hiroki')
user.hello #=> "Hello, I am hiroki."
user.hi #=> "Hi, I am hiroki."
user.my_name #=> "My name is hiroki."

しかし、書き込み用のメソッドを定義する場合はselfキーワードの使い方に注意が必要です

class User
  attr_accessor :name
  
  def initialize(name)
    @name = name
  end

  def rename_to_bob
    #selfなしでname=メソッドを呼ぶ…?
    name = 'Bob'
  end

  def rename_to_carol
    #self付きでname=メソッドを呼ぶ
    self.name = 'Carol'
  end

  def rename_to_dave
    #直接インスタンス変数を書き換える
    @name = 'Dave'
  end
end
 
#selfなしでname=メソッドを呼ぼうとするとうまくいかない
user = User.new('hiroki')

user.rename_to_bob
user.name #=> "hiroki"

user.rename_to_carol
user.name #=> "Carol"

user.rename_to_dave
user.name #=> "Dave"

#selfを使わずにname=メソッドを呼ぼうとすると、ローカル変数のnameに値を代入すると解釈してしまうため、エラーは出ないがインスタンス変数は書き換わらない
superでスーパークラスのメソッドを呼び出す

スーパークラスに定義された処理を繰り返し書く代わりにsuperを使って同名のメソッドを呼び出すことができます

class Product
  attr_reader :name, :price

  def initialize(name, price)
    @name = name
    @price = price
  end
end

class DVD < Product
  attr_reader :running_time

  def initialize(name, price, running_time)
    super(name, price)
    @running_time = running_time
  end
end

#スーパークラスのメソッドを継承できていることがわかる
dvd = DVD.new('A great movie', 1000, 120)
dvd.name #=> "A great movie"
dvd.price #=> 1000
dvd.running_time #=> 120