Menu
Coddy logo textTech

self en los métodos

Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 9 de 57.

Dentro de un método, name = value siempre crea una variable local, incluso cuando la clase tiene un setter name=. Para llamar al setter, escribe el receptor: 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

Salida:

level is a new local variable here, still nil
2

Los lectores no necesitan self.: level y self.level llaman al mismo método. El estilo habitual escribe self. solo donde Ruby lo necesita, delante de 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

Salida:

24

Llamar al setter desde initialize con self. hace que los objetos nuevos pasen la misma comprobación que los cambios posteriores, por lo que la regla está en un solo lugar:

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

Salida:

5
price must be positive

Lo que es self depende de dónde se ejecuta el código. Dentro de un método de instancia, es la instancia; en el cuerpo de la clase, fuera de todos los métodos, es la propia clase:

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

Salida:

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

Desafío

Fácil

La clase Account tiene un setter personalizado balance= que genera ArgumentError con balance cannot be negative para un valor inferior a 0. Completa initialize(owner, balance), deposit(amount) y withdraw(amount) para que cada cambio del saldo pase por ese setter con self., incluido el saldo inicial.

El código proporcionado lee el propietario y el saldo inicial, y después los comandos +n (depósito) o -n (retiro). Imprime Ada: 120 después de cada comando, o el mensaje de error y el saldo sin cambios. Un saldo inicial no válido imprime únicamente el mensaje de error.

Tu código debe ir en account.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

require_relative 'account'

# Código de entrada/salida suministrado: déjalo 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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de Ruby online