Menu
CoddyTech

Phương thức riêng tư

Thuộc phần Lập trình hướng đối tượng trong hành trình Ruby của Coddy. Bài học 17 trên 57.

Tính đóng gói (encapsulation) nghĩa là một đối tượng ẩn cách nó hoạt động và cung cấp một tập hợp nhỏ các phương thức công khai. Các phương thức mặc định là công khai. Mọi phương thức được định nghĩa sau từ private trong thân lớp đều là phương thức riêng tư: các phương thức của chính đối tượng có thể gọi phương thức đó, còn code bên ngoài thì không thể:

class Order
  def initialize(price, quantity)
    @price = price
    @quantity = quantity
  end

  def total
    subtotal + shipping
  end

  private

  def subtotal
    @price * @quantity
  end

  def shipping
    subtotal >= 50 ? 0 : 5
  end
end

order = Order.new(10, 3)
puts order.total
begin
  order.subtotal
rescue NoMethodError => e
  puts e.message
end

Đầu ra:

35
private method `subtotal' called for an instance of Order

Bên trong lớp, một phương thức riêng tư được gọi mà không có đối tượng nhận hoặc với self.. Nếu gọi phương thức đó trên một đối tượng khác, kể cả đối tượng cùng lớp, Ruby sẽ từ chối:

class Coin
  def initialize(cents)
    @cents = cents
  end

  def describe
    "#{self.label} / #{label}"
  end

  def same_as?(other)
    other.label == label
  end

  private

  def label
    "#{@cents}c"
  end
end

a = Coin.new(5)
puts a.describe
begin
  a.same_as?(Coin.new(5))
rescue NoMethodError => e
  puts e.message
end

Đầu ra:

5c / 5c
private method `label' called for an instance of Coin

private cũng có thể nhận tên một phương thức, còn def trả về tên của phương thức, vì vậy private def helper khiến một phương thức trở thành riêng tư ngay tại nơi nó được định nghĩa. Các phương thức phía trên và xung quanh vẫn là công khai:

class Greeter
  def greet(name)
    "#{salutation}, #{name}!"
  end

  private def salutation
    "Hello"
  end

  def wave
    "*waves*"
  end
end

g = Greeter.new
puts g.greet("Ada")
puts g.wave
p Greeter.private_instance_methods(false)

Đầu ra:

Hello, Ada!
*waves*
[:salutation]

Giữ các hàm hỗ trợ ở chế độ riêng tư. Các phương thức (method) công khai là lời hứa mà một lớp đưa ra với phần còn lại của chương trình; bạn có thể đổi tên hoặc xóa các phương thức riêng tư về sau mà không làm hỏng bất kỳ bên gọi nào:

class Invoice
  def total              # public: mã gọi phụ thuộc vào phương thức này
    net + tax
  end

  private                # có thể tùy ý thay đổi sau

  def net
    ...
  end

  def tax
    ...
  end
end
challenge icon

Thử thách

Dễ

Hoàn thiện lớp Order. Phương thức công khai duy nhất ngoài initialize là receipt, trả về 3 x 12.50 = 37.50, tax 7.50, total 45.00. Các phương thức riêng tư subtotal (giá nhân với số lượng), tax (20% của subtotal) và total tính các con số.

Code được cung cấp đọc các đơn hàng theo từng dòng quantity price và in từng biên nhận. Sau đó, code thử gọi tax từ bên ngoài và in tax is private khi Ruby từ chối.

Code của bạn nằm trong order.rb. main.rb chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

require_relative 'order'

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input = []
while (line = gets)
  input << line.chomp
end
orders = input.map do |line|
  quantity, price = line.split
  Order.new(quantity.to_i, price.to_f)
end
orders.each { |o| puts o.receipt }
begin
  orders[0].tax
  puts "tax is public"
rescue NoMethodError
  puts "tax is private"
end
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Ruby online