假设我有一个名为Person
的类,而人有一个名为partner
的属性。当我在其中一个partner=
对象上调用Person
时,我想设置两个对象的@partner
实例变量。以下是语法无效的示例:
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
答案 0 :(得分:2)
将attr_reader
更改为attr_accessor
并添加辅助方法:
class Person
attr_accessor :partner
def link_partners(person)
@partner = person
person.partner = self
end
end
可见性更新。根据弗雷德里克的建议。这有点冗长,但会阻止合作伙伴直接设置:
class Person
protected
attr_writer :partner
public
attr_reader :partner
def link_partners(person)
@partner = person
person.partner = self
end
end
两种实现都是这样的:
p1, p2 = Person.new, Person.new
p1.link_partners(p2)
# p2.link_partners(p1)
答案 1 :(得分:1)
您可以提供受保护的帮助程序方法,该方法由partner=
方法调用以执行实际工作。由于“外人”无法调用,因此您的所有检查和余额都可以在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
答案 2 :(得分:0)
没关系,我刚发现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
答案 3 :(得分:0)
理论上,你可以这样做:
def partner=(person)
@partner = person
person.instance_variable_set(:@partner, self)
end
但是,我认为这是神奇的。 (这不是一件好事。)而是将attr_reader
变为attr_accessor
并编写另一种方法,将两个person
s'partner
彼此设置。< / p>
答案 4 :(得分:0)
这将解决您的递归设置问题并且看起来比您的解决方案更好:
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