# Private Setter in Ruby

> 

Published: 2014-10-22
URL: https://kaochenlong.com/private-setter-in-ruby

---

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


