Leon's Blogging

Coding blogging for hackers.

Ruby - Public Protected Private

| Comments

  • public: 不管在哪都可以 call
  • private: 必須在類別內部才可以 call,不能明確指明 recevier,即使 self 也不行
  • protected: 在 publicprivate 兩者之間,不能給外面呼叫,但在類別內,是可以自由取用(要不要加 recevier 都可以)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class User
  def initialize
  end

  def public
    "public"
  end

  def call_protected
    protected
  end

  def call_private
    private
  end

  def call_protected_with_recevier
    self.protected
  end

  def call_private_with_recevier
    self.private
  end

  protected

  def protected
    "protected"
  end

  private

  def private
    "private"
  end

  # 另一種指定方式
  # protected :protected
  # private :private
end

user = User.new     # => #<User:0x007fa756804198>
user.public         # => "public"
user.protected      # NoMethodError: protected method `protected' called for #<User:0x007fa756804198>
user.private        # NoMethodError: private method `private' called for #<User:0x007fa756804198>
user.call_protected # => "protected"
user.call_private   # => "private"
user.call_protected_with_recevier # => "protected"
user.call_private_with_recevier   # NoMethodError: private method `private' called for #<User:0x007fa756804198>

另外有個例外,如果像上面的方式將 class method 放在 private 會無效

1
2
3
4
5
6
7
8
9
10
11
class A
  private

  def self.b
    puts 'hi'
  end
end

A.b
# hi
# => nil

必須使用 selfprivate_class_method

class << self opens up self’s singleton class, so that methods can be redefined for the current self object. This is used to define class/module (“static”) method. Only there, defining private methods really gives you private class methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A
  class << self
    private
    def b
      'hi'
    end
  end

  def self.c
    hello
  end
  private_class_method :c
end

A.b # NoMethodError: private method `b' called for A:Class
A.c # NoMethodError: private method `c' called for A:Class

一般都只會用 private,而用 protected 的情況如以下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class User
  attr_reader :name

  def initialize(name)
    @name = name
  end

  def ==(other_user)
    # 當兩個 instance 都要指名 receiver 時
    self.secret == other_user.secret
  end

  protected

  def secret
    "#{name}.#{name.length}"
  end
end

foo = User.new("Foo")
bar = User.new("Bar")
foo == bar # => false

參考文件

Comments