Private Setter in Ruby
之前在 Public, Protected and Private Method in Ruby 這篇文章提到,在 Ruby 裡使用 private 方法的時候,不能明確的指出 receiver,以下面這段範例來說:
class Dog
def hello
self.gossip
end
private
def gossip
puts "don't tell anyone!"
end
end
snoopy = Dog.new
snoopy.hello # => NoMethodError
snoopy.gossip # => NoMethodError
在上面這段程式碼的第 13 行,因為它明確的指出 receiver(snoopy),所以執行這行程式碼會出現會出現 NoMethodError
的錯誤;而在第 3 行,即使 receiver 是 self
也一樣是不行的。
這是在 Ruby 裡面 private 方法的設計。
不過,今天剛好有朋友拿了一段程式碼給我看,才發現原來上面這個規則原來也是有例外的,舉個例子來說:
class Dog
attr_accessor :name
private :name, :name=
def hello
self.gossip
end
def greeting1
self.name
end
def greeting2
self.name = "Snoopy"
end
private
def gossip
puts "don't tell anyone!"
end
end
snoopy = Dog.new
snoopy.hello # => NoMethodError
snoopy.gossip # => NoMethodError
snoopy.greeting1 # => NoMethodError
snoopy.greeting2 # => It Works!
在上面這段範例中用 attr_accessor
做了一個 name
的 getter 跟 setter,並且把 getter/setter 設定成 private。在第 10 行的地方呼叫了 private 的 getter,並且明確的指出 receiver 是 self
,照規則來說會出現錯誤不意外,但第 14 行用類似的方法呼叫了 private 的 setter 卻沒有出錯!
的確 private 方法不能指出明確的 receiver,但 setter 算是這個規則的例外。因為你不在前面加 self 的話,像這樣:
def greeting
name = "Snoopy"
end
這樣這個 name
不就變成區域變數的賦值了嗎?
想想看,如果在這裡呼叫 setter 不加 self 的話,那 Ruby 要怎麼分辨到底你是要呼叫 setter 還是區域變數?
話說回來,通常我們也不會沒事把 getter/setter 設定成 private,因為既然都做了 getter/setter 就是要給別人用的不是嗎?
工商服務
實體課程:Ruby on Rails 實戰課程
線上課程:五倍學院線上課程