4

从 mixin 方法中引用扩展对象上的访问器是否被认为是不好的做法?一个简单的例子:

module WindInstrument
  def play
    mouthpiece.blow  #requires a mouthpiece
  end
end

class Saxophone
  attr_reader :mouthpiece

  def initialize
    @mouthpiece = Mouthpiece.new
  end

  include WindInstrument
end

Saxophone.new.play

在这种情况下,我实际上只是将喉舌的需求直接移至 WindInstrument 模块,但在更复杂的场景中,访问器真正存在于扩展对象上才有意义呢?这只是一个不适当的关注点分离问题吗?

Mixin 对于添加不需要了解扩展对象状态的封装行为很有用。事实上,我的直觉告诉我,mixin 不应该了解任何状态。如果它需要状态知识,我通常会选择以下两种选择之一:

  • 将状态放在一个类中,并通过组合而不是通过继承层次结构添加它。我的问题是,我知道ruby​​ists 正在创建访问状态的 mixin,这使得设计更具可读性,如果不那么直观(对我来说)。

  • 将喉舌作为参数传递给模块。甚至我都可以看出这似乎使设计变得混乱,并且在红宝石世界观中感觉像是可憎的。

这段代码会打扰其他人吗?我知道那里有很多聪明的人在使用 ruby​​,所以我认为问题出在我的身上。我错过了什么?我只需要冷静一下吗?你会怎么做?

4

2 回答 2

1

我认为这与猴子修补中的相同:可以这样做,但是您必须首先确保没有其他选择(即,您不能使用您的界面修改类)其次,您必须非常明确说明(确保文档、注释和界面提到这是我们的那个方法是必需的并且将被调用),如果不是,则抛出有用的错误消息

于 2011-02-14T07:55:22.207 回答
0

Ruby 的访问器是接口,而不是实现。

例如,如果您调用person.height_in_feet=,您不知道高度实际以什么单位实现为实例变量。它可以是米、英尺或肘。

使用访问器的 mixin 的一个真实示例是Enumerable模块。虽然我没有在我创建的任何类中包含这个模块,但我对它的作用感到满意。它为您提供了方便的方法,例如mapand each_with_index,同时保持 DRY - 您可以使用“mixee”的所有方法访问的对象只有一个实现,并且map对于使用 的任何对象,只有一个定义Enumerable

于 2011-02-09T03:48:58.957 回答