Menu
Coddy logo textTech

self in Methoden

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

Innerhalb einer Methode erzeugt name = value immer eine lokale Variable, selbst wenn die Klasse einen Setter name= besitzt. Um den Setter aufzurufen, schreibe den Empfänger davor: self.name = value:

class Player
  attr_accessor :level

  def initialize
    @level = 1
  end

  def broken_level_up
    level = level + 1
  rescue NoMethodError
    puts "level is a new local variable here, still nil"
  end

  def level_up
    self.level = level + 1
  end
end

p1 = Player.new
p1.broken_level_up
p1.level_up
puts p1.level

Ausgabe:

level is a new local variable here, still nil
2

Leser benötigen kein self.: level und self.level rufen dieselbe Methode auf. Der übliche Stil verwendet self. nur dort, wo Ruby es benötigt, vor einem Setter:

class Rect
  attr_accessor :w, :h

  def initialize(w, h)
    @w = w
    @h = h
  end

  def area
    w * h
  end

  def double!
    self.w = w * 2
    self.h = self.h * 2
    self
  end
end

puts Rect.new(2, 3).double!.area

Ausgabe:

24

Wenn der Setter aus initialize mit self. aufgerufen wird, bestehen neue Objekte dieselbe Prüfung wie spätere Änderungen, sodass die Regel an einer einzigen Stelle steht:

class Product
  attr_reader :price

  def initialize(price)
    self.price = price
  end

  def price=(value)
    raise ArgumentError, "price must be positive" if value <= 0

    @price = value
  end
end

puts Product.new(5).price
begin
  Product.new(0)
rescue ArgumentError => e
  puts e.message
end

Ausgabe:

5
price must be positive

Wovon self abhängt, hängt davon ab, wo der Code ausgeführt wird. Innerhalb einer Instanzmethode ist es die Instanz; im Klassenrumpf, außerhalb jeder Methode, ist es die Klasse selbst:

class Robot
  puts "in the class body, self is #{self}"

  def whoami
    "in a method, self is a #{self.class}"
  end
end

puts Robot.new.whoami

Ausgabe:

in the class body, self is Robot
in a method, self is a Robot
challenge icon

Aufgabe

Einfach

Die Klasse Account verfügt über einen benutzerdefinierten Setter balance=, der bei einem Wert unter 0 ArgumentError mit balance cannot be negative auslöst. Vervollständige initialize(owner, balance), deposit(amount) und withdraw(amount), sodass jede Änderung des Kontostands über diesen Setter mit self. erfolgt, einschließlich des Anfangskontostands.

Der bereitgestellte Code liest den Besitzer und den Anfangskontostand ein, anschließend die Befehle +n (Einzahlung) oder -n (Abhebung). Nach jedem Befehl gibt er Ada: 120 oder die Fehlermeldung und den unveränderten Kontostand aus. Bei einem ungültigen Anfangskontostand wird nur die Fehlermeldung ausgegeben.

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

Probier es selbst

require_relative 'account'

# Gelieferter Ein-/Ausgabecode: belasse ihn wie er ist
input = []
while (line = gets)
  input << line.chomp
end
begin
  account = Account.new(input[0], input[1].to_i)
  input.drop(2).each do |cmd|
    begin
      amount = cmd[1..].to_i
      cmd.start_with?("+") ? account.deposit(amount) : account.withdraw(amount)
    rescue ArgumentError => e
      puts e.message
    end
    puts "#{account.owner}: #{account.balance}"
  end
rescue ArgumentError => e
  puts e.message
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