🍣
Ruby初心者向け:@nameとself.nameの違いを徹底解説
Ruby初心者向け:@nameとself.nameの違いを徹底解説
はじめに
Rubyを学び始めたとき、こんなコードを書いたことはありませんか?
class User
def initialize(name)
@name = name
end
def name
@name
end
def set_name(new_name)
@name = new_name
end
def greet
puts "こんにちは、#{@name}です"
end
end
でも先輩エンジニアから「attr_accessorとselfを使った方がいいよ」と言われて、こんな風に書き直すように言われた経験はありませんか?
class User
attr_accessor :name
def initialize(name)
self.name = name
end
def greet
puts "こんにちは、#{self.name}です"
end
end
「@nameの方が分かりやすくない?」と思うかもしれませんが、実はself.nameを使うことには重要な理由があります。
attr_accessorとは?
まずattr_accessorについて理解しましょう。
# この1行は...
attr_accessor :name
# 実際にはこの2つのメソッドを自動生成している
def name
@name
end
def name=(value)
@name = value
end
つまり、attr_accessor :nameと書くだけで:
-
ゲッターメソッド(
name):値を取得する -
セッターメソッド(
name=):値を設定する
この2つが自動的に作られるのです。
セッターメソッドの特殊な書き方
Rubyではname=というメソッドを特別扱いします:
# この2つは全く同じ意味
user.name = "田中"
user.name=("田中") # 実際はこれが呼ばれている
つまり=を使った代入のような書き方でも、実際にはメソッド呼び出しなのです。
self.nameがセッターを呼ぶ仕組み
def initialize(name)
self.name = name # これがどう動くか?
end
実行の流れ:
-
self.name = "yamada"と書く - Rubyが「
name=メソッドはあるかな?」と探す -
attr_accessorで作られたname=メソッドを発見 -
name=("yamada")が実行される
実際に確認してみましょう:
class User
def initialize(name)
puts "initializeが呼ばれました: #{name}"
self.name = name
puts "initializeが終わりました"
end
def name=(new_name)
puts "name=メソッドが呼ばれました: #{new_name}"
@name = new_name
puts "name=メソッドが終わりました"
end
end
user = User.new("yamada")
出力:
initializeが呼ばれました: yamada
name=メソッドが呼ばれました: yamada
name=メソッドが終わりました
initializeが終わりました
なぜself.nameを使うべきなのか?
1. 将来の変更に強い
例えば、「名前は必ず大文字で始まるようにしたい」という要求が来たとします。
@nameを直接使った場合:
class User
def initialize(name)
@name = name.capitalize # ここを修正
end
def set_name(new_name)
@name = new_name.capitalize # ここも修正
end
def some_method
@name = "yamada" # あ!大文字化を忘れた!
end
def greet
puts "こんにちは、#{@name}です" # → "yamadaです"(小文字のまま)
end
end
self.nameを使った場合:
class User
attr_accessor :name
def initialize(name)
self.name = name # セッターを使用
end
def name=(new_name)
@name = new_name.capitalize # ここだけ修正すればOK
end
def some_method
self.name = "yamada" # セッターを通るので自動的に大文字化
end
def greet
puts "こんにちは、#{self.name}です" # → "Yamadaです"(正しく大文字化)
end
end
2. 一貫性のあるインターフェース
# クラス外部での使い方
user.name = "田中" # セッター経由
puts user.name # ゲッター経由
# クラス内部でも同じインターフェースを使う
self.name = new_value # セッター経由
puts self.name # ゲッター経由
3. デバッグが楽
class User
attr_accessor :name
def name=(value)
puts "nameが変更されました: #{value}" # デバッグ用
@name = value
end
end
実践例で比較してみよう
❌ 推奨されない書き方
class User
def initialize(name, email)
@name = name
@email = email&.downcase # emailだけ小文字化
end
def name
@name
end
def email
@email
end
def set_name(new_name)
@name = new_name # 他の場所では大文字化の処理がない
end
def set_email(new_email)
@email = new_email&.downcase
end
end
✅ 推奨される書き方
class User
attr_accessor :name, :email
def initialize(name, email)
self.name = name
self.email = email
end
def name=(new_name)
@name = new_name&.strip&.capitalize
end
def email=(new_email)
@name = new_email&.strip&.downcase
end
end
まとめ
-
@nameを直接使う → バラバラに管理、ミスしやすい -
self.nameを使う → 1箇所で管理、ミスしにくい
最初は@nameの方が直感的に感じるかもしれませんが、self.nameを使うことで:
- 保守しやすいコードになる
- 一貫性のあるインターフェースを提供できる
- 将来の変更に対応しやすくなる
慣れてしまえば、「メソッド経由でアクセスする」という一貫したルールの方が分かりやすくなります。
ぜひ今日からattr_accessorとselfを使ったコードを書いてみてください!
Discussion