Menu
Coddy logo textTech

self nei metodi

Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 9 di 57.

All'interno di un metodo, name = value crea sempre una variabile locale, anche quando la classe ha un setter name=. Per chiamare il setter, scrivi il ricevitore: 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

Output:

level is a new local variable here, still nil
2

I lettori non hanno bisogno di self.: level e self.level chiamano lo stesso metodo. Di solito si scrive self. solo dove Ruby ne ha bisogno, davanti a un 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

Output:

24

Chiamare il setter da initialize con self. fa sì che i nuovi oggetti superino lo stesso controllo delle modifiche successive, così la regola è definita in un unico punto:

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

Output:

5
price must be positive

Ciò che self rappresenta dipende da dove viene eseguito il codice. All'interno di un metodo di istanza è l'istanza; nel corpo della classe, al di fuori di qualsiasi metodo, è la classe stessa:

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

Output:

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

Sfida

Facile

La classe Account ha un setter personalizzato balance= che genera ArgumentError con balance cannot be negative per un valore inferiore a 0. Completa initialize(owner, balance), deposit(amount) e withdraw(amount) in modo che ogni modifica del saldo passi attraverso quel setter con self., incluso il saldo iniziale.

Il codice fornito legge il proprietario e il saldo iniziale, poi i comandi +n (deposito) o -n (prelievo). Stampa Ada: 120 dopo ogni comando oppure il messaggio di errore e il saldo invariato. Un saldo iniziale non valido stampa solo il messaggio di errore.

Il tuo codice va in account.rb. main.rb contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

require_relative 'account'

# Código de entrada/salida proporcionado: mantenlo tal como está
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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Ruby online