0
0

More than 3 years have passed since last update.

クラスとインスタンスを使って実装しよう③

Posted at

以下のプログラムを実行するとエラーが起きます。
①エラーが起きた原因
②正しいソースコード

実行したプログラム
class Student
  def set_name(name)
    @name = name
  end

  def self.introduce
    puts "私の名前は#{@name}です。"
  end
end

student = Student.new
student.set_name("山田太郎")
student.introduce

①エラーが起きた原因

Studentクラスのメソッドintroduceがインスタンスメソッドではなくクラスメソッドになってしまっていること(メソッドの定義にself.がついている)。

②正しいソースコード
class Student
  def set_name(name)
    @name = name
  end

  def introduce
    puts "私の名前は#{@name}です。"
  end
end

student = Student.new
student.set_name("山田太郎")
student.introduce

クラスメソッドとインスタンスメソッドを間違えたことによりエラーが起きた問題。

問題文のソースコードでは、introduceメソッドはdef self.introduceと定義されており、クラスメソッドになっています。
※クラスメソッドはメソッド名の先頭にself.をつけたメソッドです。

問題のソースコード
def self.introduce
  puts "私の名前は#{@name}です。"
end

最後の行では、このクラスメソッドintroduceをインスタンスが呼び出してしまっています。クラスメソッドはインスタンスからは呼び出せないので、エラーになります。

問題のソースコード

student.introduce # introduceメソッドはクラスメソッドなのでインスタンスstudentからは呼び出せない
introduceメソッドの処理を見ると、インスタンス変数@nameが使われています。@が先頭についた変数はインスタンス変数となり、インスタンスメソッド全てで同じ値が使えるようになります。

今回の問題では以下のインスタンスメソッドset_nameで、インスタンス変数@nameに生徒の名前を代入しています。
※set_nameメソッドはself.がついていないので、インスタンスメソッドです。

問題のソースコード
def set_name(name)
  @name = name # 引数のnameをインスタンス変数@nameに代入
end

問題のソースコード

student = Student.new # Studentクラスのインスタンスを作る
student.set_name("山田太郎") # インスタンスメソッドset_nameを呼び出し
set_nameメソッドの@name = nameの箇所では、引数として渡されてきた"山田太郎"という文字列をインスタンス変数@nameに代入しています。
これで、他のインスタンスメソッドの中でも@nameと書くと"山田太郎"という値が使える状態になります。

しかし、クラスメソッドではインスタンス変数は使えません。よってintroduceメソッドの中のputs "私の名前は#{@name}です。"という処理はクラスメソッドの状態では使えないことになります。

問題のソースコード

def self.introduce
  puts "私の名前は#{@name}です。" # @nameはクラスメソッド内では使えない
end

そこでintroduceメソッドをクラスメソッドからインスタンスメソッドに変更します。self.を削除するだけです。

def introduce
  puts "私の名前は#{@name}です。"
end

これでintroduceメソッドはインスタンスメソッドになり、puts "私の名前は#{@name}です。"はputs "私の名前は山田太郎です。"という意味になります。

更にintroduceメソッドの呼び出しはインスタンスから行えるようになったので、student.introduceの箇所も動くようになります。

正しいソースコード
class Student
  def set_name(name)
    @name = name
  end

  def introduce
    puts "私の名前は#{@name}です。"
  end
end

student = Student.new
student.set_name("山田太郎")
student.introduce
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0