Menu
CoddyTech

self dans les méthodes

Fait partie de la section Programmation orientée objet du Journey Ruby de Coddy. Leçon 9 sur 57.

À l’intérieur d’une méthode, name = value crée toujours une variable locale, même lorsque la classe possède un accesseur en écriture name=. Pour appeler l’accesseur en écriture, indique le récepteur : 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

Sortie :

level is a new local variable here, still nil
2

Les lecteurs n’ont pas besoin de self. : level et self.level appellent la même méthode. En général, on écrit self. uniquement là où Ruby en a besoin, devant un accesseur en écriture :

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

Résultat :

24

Appeler le setter depuis initialize avec self. fait passer aux nouveaux objets le même contrôle que lors des modifications ultérieures, ainsi la règle n’est définie qu’à un seul endroit :

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

Sortie :

5
price must be positive

La valeur de self dépend de l’endroit où le code s’exécute. Dans une méthode d’instance, c’est l’instance ; dans le corps de la classe, en dehors de toute méthode, c’est la classe elle-même :

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

Résultat :

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

Défi

Facile

La classe Account possède un accesseur personnalisé balance= qui lève ArgumentError avec balance cannot be negative pour une valeur inférieure à 0. Complète initialize(owner, balance), deposit(amount) et withdraw(amount) afin que chaque modification du solde passe par cet accesseur avec self., y compris le solde initial.

Le code fourni lit le propriétaire et le solde initial, puis les commandes +n (dépôt) ou -n (retrait). Il affiche Ada: 120 après chaque commande, ou le message d’erreur et le solde inchangé. Un solde initial invalide affiche uniquement le message d’erreur.

Ton code va dans account.rb. main.rb contient le code d’entrée/sortie fourni et ne peut pas être modifié.

Essayez vous-même

require_relative 'account'

# Code d’entrée/sortie fourni : conservez-le tel quel
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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Compilateur Ruby en ligne