0

假设我有一个名为的类Person,而 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
4

5 回答 5

2

将 更改attr_reader为 anattr_accessor并添加一个辅助方法:

class Person

  attr_accessor :partner

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

更新可见性。根据下面 Frederick 的建议。这有点冗长,但会阻止直接设置合作伙伴:

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)
于 2013-07-21T21:42:40.477 回答
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
于 2013-07-21T22:40:38.383 回答
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
于 2013-07-21T21:46:09.493 回答
0

理论上,您可以按以下方式执行此操作:

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

但是,我认为这很神奇。(这不是一件好事。)相反,将sattr_reader变成 anattr_accessor并编写一个不同的方法来将两个persons设置partner为彼此。

于 2013-07-21T21:49:36.553 回答
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
于 2013-07-21T21:52:56.317 回答