Public, private và protected trong Ruby: visibility là contract

Method visibility mô tả API boundary của object.

Public

Public method gọi với explicit receiver:

1
account.balance

Đây là contract bên ngoài.

Private

Private method chỉ gọi không có explicit receiver (ngoại lệ syntax như setter có nuance riêng):

1
2
3
4
5
6
7
8
9
10
11
class Account
def close
audit
end

private

def audit
# ...
end
end

Private không phải security boundary. send, reflection và reopen class vẫn truy cập được. Nó là tín hiệu thiết kế: caller không nên phụ thuộc method này.

Protected

Protected method có thể gọi với explicit receiver khi receiver phù hợp trong hierarchy/context:

1
2
3
4
5
6
7
8
9
class Account
def richer_than?(other)
balance > other.balance
end

protected

attr_reader :balance
end

Hữu ích cho object cùng loại cần cộng tác trên internal state, nhưng ít dùng hơn private.

Class methods

Visibility của instance method và singleton method khác nhau:

1
2
3
4
5
6
7
8
9
class Token
class << self
private

def secret
"x"
end
end
end

private_class_method cũng có thể dùng.

Chọn visibility

  • Public: stable behavior cho caller.
  • Private: implementation detail.
  • Protected: collaboration nội bộ giữa related objects.

Giảm public surface giúp refactor dễ hơn. Mỗi public method là một lời hứa; codebase lâu năm thường đau vì đã hứa quá nhiều lúc còn trẻ.