Menu
Coddy logo textTech

Geschützte Methoden

Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 18 von 57.

Eine geschützte Methode liegt zwischen public und private. Code außerhalb kann sie nicht aufrufen, aber jedes Objekt derselben Klasse kann sie für ein anderes Objekt aufrufen. Dadurch können zwei Objekte Daten vergleichen, die sie dem Rest des Programms nicht zeigen:

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

Ausgabe:

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

Der Unterschied zu private zeigt sich, wenn der Empfänger ein anderes Objekt ist. other.balance funktioniert bei einer geschützten Methode und schlägt bei einer privaten Methode fehl:

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)

Ausgabe:

3
private refused other.hidden

protected funktioniert auch mit attr_reader, der üblichen Methode, um einen Wert nur unter Objekten einer Klasse zu teilen, zum Beispiel um zu entscheiden, welches von zwei Objekten gewinnt:

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

Ausgabe:

true
["Ada"]

Wähle die engste passende Ebene. public ist für die Schnittstelle der Klasse, protected für Daten, mit denen Objekte der Klasse einander vergleichen, und private für alles andere:

public      # jeder: order.total
protected   # Objekte der Klasse: other.balance innerhalb von Account
private     # nur das Objekt selbst: subtotal, self.subtotal
challenge icon

Aufgabe

Einfach

Vervollständige die Klasse Account. Der Kontostand soll nur von anderen Konten gelesen werden können: Mache seinen Reader geschützt. richer_than?(other) vergleicht die Kontostände, transfer_to(other, amount) überweist Geld über die geschützte Methode receive(amount) des anderen Kontos auf ein anderes Konto und gibt true zurück oder gibt false zurück, wenn der Kontostand zu niedrig ist. to_s gibt nur den Namen des Besitzers zurück.

Der bereitgestellte Code liest die beiden Besitzer und Kontostände ein, anschließend die Befehle transfer a b 50 und gibt ok oder refused aus. Danach gibt er Ada is richer (oder Bo is richer oder equal) aus und versucht schließlich, balance von außerhalb zu lesen, wobei balance is protected ausgegeben wird, wenn Ruby dies verweigert.

Dein Code gehört in account.rb. main.rb enthält den bereitgestellten Eingabe-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

require_relative 'account'

# Bereitgestellter Ein-/Ausgabecode: belasse ihn wie er ist
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 iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Ruby-Compiler