Menu
Coddy logo textTech

Korumalı Metotlar

Coddy'nin Ruby Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 18 / 57.

protected bir metot, public ve private arasında yer alır. Dışarıdaki kod onu çağıramaz; ancak aynı sınıftaki herhangi bir nesne, bu metodu başka bir nesne üzerinde çağırabilir. Bu, iki nesnenin programın geri kalanına göstermedikleri verileri karşılaştırmasına olanak tanır:

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

Çıktı:

true
protected method `balance' called for an instance of Account

private ile arasındaki fark, alıcı başka bir nesne olduğunda ortaya çıkar. other.balance, protected bir yöntem için çalışır, private bir yöntem içinse başarısız olur:

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)

Çıktı:

3
private refused other.hidden

protected, örneğin iki nesneden hangisinin kazandığına karar vermek için bir değeri yalnızca aynı sınıftaki nesneler arasında paylaşmanın yaygın yolu olan attr_reader ile de çalışır:

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

Çıktı:

true
["Ada"]

İşe yarayan en dar düzeyi seçin. public sınıfın arayüzü, protected sınıfın nesnelerinin birbirleriyle karşılaştırdığı veriler, private ise diğer her şey içindir:

public      # herkes: order.total
protected   # sınıfın nesneleri: Account içindeki other.balance
private     # yalnızca nesnenin kendisi: subtotal, self.subtotal
challenge icon

Görev

Kolay

Account sınıfını tamamla. Bakiye yalnızca diğer hesaplar tarafından okunabilir olmalı: okuyucusunu protected yap. richer_than?(other) bakiyeleri karşılaştırır, transfer_to(other, amount) parayı diğer hesabın protected yöntemi receive(amount) aracılığıyla başka bir hesaba aktarır ve true döndürür; bakiye yetersiz olduğunda ise false döndürür. to_s yalnızca sahibin adını döndürür.

Sağlanan kod iki sahibin ve bakiyelerin bilgilerini okur, ardından transfer a b 50 komutlarını işleyerek ok veya refused yazdırır. Sonra Ada is richer (veya Bo is richer ya da equal) yazdırır ve son olarak dışarıdan balance değerini okumayı dener; Ruby bunu reddettiğinde balance is protected yazdırır.

Kodun account.rb dosyasına yazılmalı. main.rb sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'account'

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakı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
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Ruby derleyicisi