Phương thức được bảo vệ
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 18 trên 57.
Phương thức protected nằm giữa public và private. Code bên ngoài không thể gọi phương thức này, nhưng mọi đối tượng thuộc cùng một lớp đều có thể gọi phương thức đó trên một đối tượng khác. Nhờ vậy, hai đối tượng có thể so sánh dữ liệu mà chúng không hiển thị cho phần còn lại của chương trình:
class Account
def initialize(owner, balance)
@owner = owner
@balance = balance
end
def richer_than?(other)
balance > other.balance
end
protected
def balance
@balance
end
end
ada = Account.new("Ada", 500)
bo = Account.new("Bo", 300)
puts ada.richer_than?(bo)
begin
ada.balance
rescue NoMethodError => e
puts e.message
endĐầu ra:
true
protected method `balance' called for an instance of AccountSự khác biệt so với private thể hiện khi đối tượng nhận là một đối tượng khác. other.balance hoạt động với phương thức được bảo vệ nhưng không hoạt động với phương thức riêng tư:
class Sample
def initialize(n)
@n = n
end
def compare_protected(other)
other.guarded + guarded
end
def compare_private(other)
other.hidden + hidden
rescue NoMethodError
"private refused other.hidden"
end
protected
def guarded
@n
end
private
def hidden
@n
end
end
a = Sample.new(1)
b = Sample.new(2)
puts a.compare_protected(b)
puts a.compare_private(b)Đầu ra:
3
private refused other.hiddenprotected cũng hoạt động với attr_reader, cách thường dùng để chia sẻ một giá trị chỉ giữa các đối tượng thuộc cùng một lớp, chẳng hạn để quyết định đối tượng nào trong hai đối tượng thắng:
class Player
attr_reader :name
def initialize(name, rating)
@name = name
@rating = rating
end
def stronger?(other)
rating > other.rating
end
protected
attr_reader :rating
end
a = Player.new("Ada", 1200)
b = Player.new("Bo", 1100)
puts a.stronger?(b)
puts [a, b].select { |pl| pl.stronger?(b) }.map(&:name).inspectĐầu ra:
true
["Ada"]Chọn mức độ hạn chế nhất vẫn đáp ứng nhu cầu. public dành cho giao diện của lớp, protected dành cho dữ liệu mà các đối tượng của lớp so sánh với nhau, còn private dành cho mọi thứ khác:
public # Bất kỳ ai: order.total
protected # Các đối tượng của lớp: other.balance bên trong Account
private # Chỉ chính đối tượng đó: subtotal, self.subtotalThử thách
DễHoàn thiện lớp Account. Chỉ các tài khoản khác mới có thể đọc số dư, hãy đặt phương thức đọc của nó ở phạm vi protected. richer_than?(other) so sánh số dư, transfer_to(other, amount) chuyển tiền sang tài khoản khác thông qua phương thức protected receive(amount) của tài khoản đó và trả về true, hoặc trả về false khi số dư quá thấp. to_s chỉ trả về tên chủ sở hữu.
Code được cung cấp đọc tên chủ sở hữu và số dư của hai tài khoản, sau đó xử lý các lệnh transfer a b 50, rồi in ra ok hoặc refused. Tiếp theo, code in ra Ada is richer (hoặc Bo is richer, hoặc equal) rồi thử đọc balance từ bên ngoài, in ra balance is protected khi Ruby từ chối.
Code của bạn nằm trong account.rb. main.rb chứa code đầu vào/đầu ra được cung cấp và không thể chỉnh sửa.
Tự làm thử
require_relative 'account'
# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input = []
while (line = gets)
input << line.chomp
end
accounts = input[0..1].map do |line|
owner, balance = line.split
Account.new(owner, balance.to_i)
end
a, b = accounts
input.drop(2).each do |line|
_, from, to, amount = line.split
source = from == "a" ? a : b
target = to == "a" ? a : b
puts source.transfer_to(target, amount.to_i) ? "ok" : "refused"
end
if a.richer_than?(b) then puts "#{a} is richer"
elsif b.richer_than?(a) then puts "#{b} is richer"
else puts "equal"
end
begin
a.balance
puts "balance is public"
rescue NoMethodError
puts "balance is protected"
end
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
1Lớp và đối tượng
Làm việc với tệpĐịnh nghĩa lớpBiến instancePhương thức và selfto_s và inspectÔn tập: thẻ thư viện4Tính đóng gói
Phương thức riêng tưPhương thức được bảo vệPhương thức thiết lập riêng tưBảo vệ trạng tháiÔn tập: máy bán hàng tự động7Tính đa hình và duck typing
Tính đa hìnhDuck typingPhương thức trừu tượngcase và lớpÔn tập: phương thức thanh toán2Phương thức truy cập và self
Phương thức đọc và ghiPhương thức gán tùy chỉnhself trong phương thứcĐịnh danh và tính bằng nhauÔn tập: Danh sách liên hệTự luyện tập: Trình biên dịch Ruby online