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 № 1Changer 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 person
s " partner
s 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