Private classes in Ruby
Tại sao private? Một trong những cách phổ biến nhất để làm cho một số đoạn code của bạn dễ hiểu hơn và rõ ràng hơn là trích xuất một lớp. Tuy nhiên, nhiều lần lớp này không dành cho việc sử dụng một cách public. Đó là một chi tiết thực hiện của một lớp lớn hơn. Nó không nên được sử dụng được bất ...
Tại sao private?
Một trong những cách phổ biến nhất để làm cho một số đoạn code của bạn dễ hiểu hơn và rõ ràng hơn là trích xuất một lớp. Tuy nhiên, nhiều lần lớp này không dành cho việc sử dụng một cách public. Đó là một chi tiết thực hiện của một lớp lớn hơn. Nó không nên được sử dụng được bất cứ ai khác, nhưng mô-đun trong đó đã được định nghĩa. Vậy làm thế nào để chúng ta che giấu được lớp học đó để những người khác không sử dụng? Đôi khi nó có ý nghĩa, để xác định các lớp riêng tư. Ví dụ nếu logic đặc biệt đã được di chuyển vào một lớp liên quan cho các lý do đóng gói. Sau đó, không cần phải rời khỏi lớp là công khai. Một lớp Product là một ví dụ hợp lý. Mỗi sản phẩm được đặc trưng bởi số serial cụ thể của nó. Tuy nhiên, lớp Sản phẩm không chịu trách nhiệm tạo ra số sê-ri. Nó là để đóng gói logic vào một lớp Serial riêng biệt. Thậm chí nhiều hơn, nếu số serial chứa logic thêm nữa:
class Product
  class Serial
    def initialize
      @date = Date.today
    end
    def code
      "#{@date}/#{object_id}"
    end
  end
  attr_reader :serial
  def initialize
    @serial = Serial.new
  end
  def code
    serial.code
  end
end
Lớp Product có thể sử dụng Serial một cách tự do: Một Product tạo mới với Serrial
Product.new.code # => "2017-06-11/32713960"
Mặc dù lớp Serial có thể truy cập bên ngoài:
Product::Serial.new # => #<Product::Serial:0x00000002be1548 ... >
Sử dụng private_constant
class Product
  class Serial
    def initialize
      @date = Date.today
    end
    def code
      "#{@date}/#{object_id}"
    end
  end
  # explizit privat:
  private_constant :Serial
  attr_reader :serial
  def initialize
    @serial = Serial.new
  end
  def code
    serial.code
  end
end
Lớp Serial được khai báo riêng bằng cách sử dụng Module # private_constant. Đó là lý do tại sao nó không thể được instantiated trực tiếp nữa:
Product::Serial.new # => NameError: private constant Product::Serial referenced
Vì vậy, Product là công khai mà bạn phơi bày cho các phần khác của hệ thống và Product :: Serial chỉ là một chi tiết thực hiện. Bạn cũng có thể không thử trực tiếp Product :: Serial trực tiếp, nhưng thông qua Product công khai mà khách hàng sẽ sử dụng.