【问题标题】:Maintain instance reference维护实例引用
【发布时间】:2026-01-31 22:25:01
【问题描述】:

我已经为此奋斗了两个小时,但无法解决。想象一下我有这个课程:

class SimpleExpression
attr_writer :value

def initialize(value)
    @value = value
end

def evaluate
    @value
end

然后我想像这样实例化它:

exp1 = SimpleExpression.new(true)
exp3 = exp1.not
p exp3.evaluate # This should give me false
exp1.value = false
p exp3.evaluate # This should give me true now

我真的不知道如何在 exp3 上维护 exp1 的引用,我尝试在 SimpleExpression 上创建一个方法来否定值并返回 self 但这显然不起作用,因为我会同时更改两个实例.谢谢。 PS:不应该是SimpleExpression中的方法,因为我真的不知道怎么写,所以我没有写。

【问题讨论】:

  • @SebastianPalma:当然不是。那不会回复evaluate
  • “维护引用”是什么意思?这是什么意思,为什么它很重要?
  • 我编辑了代码,做puts时出错了。我需要(以某种方式)在 not 和简单表达式之间进行组合。如您所见,如果我否定 exp1,则 exp1 保持不变(true),但 exp3 现在应该是对 exp1 的“否定”引用(在示例中为 false),因此当我将 exp1 设置为 false 时,现在 exp3 应该为 true。
  • @Delsh:啊,我明白了。确实很棘手/不明显:)
  • class SimpleExpression 没有匹配的 end。该类没有实例方法not。请缩进每一级代码(两个空格是 Ruby 约定),以 attr_writer :value 开头。

标签: ruby oop reference composition


【解决方案1】:

如果是简单的“断开”否定,那么实现就很简单了:

def not
  SimpleExpression.new(!value)
end

这里,更改exp1 不会影响exp3

exp1 = SimpleExpression.new(true)
exp3 = exp1.not
p exp3.evaluate # => false
exp1.value = false
p exp3.evaluate # => false

但是让它们“活”起来需要一些更高级的东西。我在想,一些包装对象。比如这样:

class SimpleExpression
  attr_accessor :value

  def initialize(value)
    @value = value
  end

  def evaluate
    @value
  end

  def not
    NegationWrapper.new(self)
  end

  private

  class NegationWrapper < DelegateClass(self)
    def evaluate
      !__getobj__.evaluate
    end
  end
end

exp1 = SimpleExpression.new(true)
exp3 = exp1.not
p exp3.evaluate # => false
exp1.value = false
p exp3.evaluate # => true

【讨论】:

  • 如果SimpleExpression 可以在构造函数中接受另一个表达式,而不仅仅是值,我们可以放弃包装对象。然后是几个 if 语句的问题。
  • 感谢您的解决方案!我真的很好奇如果你可以在构造函数中添加另一个表达式会怎么样,这对不使用包装器有何帮助?谢谢!
  • @Delsh:花几天时间尝试自己解决。告诉我结果和发现。 :)
  • 会的!谢谢!
  • 是的,最初的想法是对每个(和,或,不)操作都这样做!问题是我什至不能让它工作,所以我重新调整了问题的大小。将尝试双向进行!谢谢