/ / Définition de variables d'instance sur différents objets de la même classe - ruby

Définition de variables d'instance sur différents objets de la même classe - ruby

Disons que j'ai une classe appelée Person et la personne a un attribut appelé partner. Quand j'appelle partner= sur l'un des Person objets, je souhaite définir le @partner variable d'instance des deux objets. Voici un exemple avec une syntaxe incorrecte:

class Person

attr_reader :partner

def partner=(person)

# reset the old partner instance variable if it exists
partner.@partner = nil if partner

# set the partner attributes
@partner = person
person.@partner = self
end
end

Réponses:

2 pour la réponse № 1

Changer la attr_reader à un attr_accessor et ajoutez une méthode d'assistance:

class Person

attr_accessor :partner

def link_partners(person)
@partner = person
person.partner = self
end
end

Mise à jour pour la visibilité. Basé sur la suggestion de Frederick ci-dessous. C'est un peu plus détaillé, mais cela empêchera le partenaire d'être défini directement:

class Person
protected
attr_writer :partner

public
attr_reader :partner

def link_partners(person)
@partner = person
person.partner = self
end
end

Les deux implémentations fonctionnent comme ceci:

p1, p2 = Person.new, Person.new
p1.link_partners(p2)
# p2.link_partners(p1)

1 pour la réponse № 2

Vous pouvez fournir une méthode d'assistance protégée qui est appelée par votre partner= méthode pour faire le travail réel. Puisqu'il ne peut pas être appelé par des «étrangers», tous vos contrôles et soldes peuvent être conservés dans votre partner=:

class Person
attr_reader :partner

def partner=(person)
@partner.set_partner(nil) if @partner
set_partner(person)
person.set_partner(self) if person
end

def set_partner(person)
@partner = person
end

protected :set_partner
end

0 pour la réponse № 3

Peu importe, je viens de découvrir instance_variable_set.

class Person

attr_reader :partner

def partner=(person)

# reset the old partner instance variable if it exists
partner.instance_variable_set(:@partner, nil) if partner

# set the partner attributes
@partner = person
person.instance_variable_set(:@partner, self)
end
end

0 pour la réponse № 4

En théorie, vous pouvez procéder comme suit:

def partner=(person)
@partner = person
person.instance_variable_set(:@partner, self)
end

Cependant, je considérerais cela comme magique. (Ce n'est pas une bonne chose.) attr_reader dans un attr_accessor et écrivez une méthode différente pour définir deux persons " partners entre eux.


0 pour la réponse № 5

Cela résoudra votre problème avec un ensemble récursif et sera meilleur que votre solution:

class Partner
attr_reader :partner
def set_partner(person, recursive = true)
# reset previous partner
@partner.set_partner(nil, false) if recursive && @partner

# set new partner
@partner = person
@partner.set_partner(self, false) if recursive
end
alias_method :partner=, :set_partner
end