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