Ruby Mixin 对对象的依赖

标签 ruby

我对 ruby​​ 中模块的使用感到困惑。具体来说,当模块混入类中时,模块中的对象实例变量/方法应该如何访问。考虑以下示例。

class A
  include B

  def initialize(my_var)
    @my_var = my_var
    @result = nil
  end

  def get_result
    @result = foo
  end

end

module B

  def foo
    "Result of #{@my_var}"
  end

end

在上面的例子中,模块B的设计方式是,它期望封装对象定义变量my_var。这是一个好的设计吗?感觉不对,因为在这种情况下,模块 B 在某种程度上依赖于类 A。构造模块 B 的另一种方法是这样的。

module B

  def foo(my_var)
    "Result of #{my_var}"
  end

end

在此版本中,该方法接受一个参数并执行必要的计算并返回一个值。这更清晰,但这可能是一个人为的例子,因为在许多现实世界的场景中,事情要复杂得多。

而且,它不仅仅是关于实例变量。我认为同样的问题也适用于实例方法。我们是否可以构造一个模块,期望封装对象具有某些方法和/或实例变量?在这种情况下设计解决方案的正确方法是什么?

我查看了与此问题密切相关的几个 stackoverflow 线程,但找不到满意的答案。预先感谢您的所有回答

最佳答案

在第二个示例中,foo并不是真正的方法,而是一个过程。方法的区别在于它具有对接收者的特权访问权限,即 self 。但是你的第二个foo没有任何用处!那么,为什么要让它成为一种方法呢?您可以使用 BASIC 中的过程执行相同的操作。

访问 self 完全没问题在方法中,这就是方法的用途。

Ruby 本身无法声明 mixin 到底期望什么 self不过,除了文档之外,还是要完成它的工作。但这很常见:Comparable预计self回复<=> , Enumerable预计self回复each ,例如。

我称这些为“杠杆混合”,因为它们的作用就像一个杠杆:你只需要自己提供一个很小的力(一个 each 方法),但它们允许你做很多事情 繁重的工作。

这与 Ruby 中的其他类型的期望没有太大不同。 Array#join(sep)预计sep回复to_str以及要响应的数组元素 to_s , Array#[](idx)预计idx回复to_intRange成员资格测试方法期望左侧元素响应 <=>Range迭代方法( eachto_astep 、...)期望左侧元素响应 succEnumerable#sort期望可枚举的元素响应 <=>等等等等。

将期望寄托在self上与将它们放置在任何其他物体上没有太大区别。

这些“期望”通常称为“协议(protocol)”。对象遵守协议(protocol)(它们支持的消息集以及它们如何对这些消息使用react),并且依赖于其他对象的协议(protocol)。例如,您可以说 Enumerable mixin 取决于 Iteration协议(protocol)。然而,除了简单的文档之外,Ruby 语言中没有任何结构来表达此类协议(protocol)。

但是,一般来说在 Ruby 中使用实例变量并不是很面向对象。 OO 是关于消息传递的,但 Ruby 只为方法而不是变量提供消息传递(例如,与 Self 不同,实例变量是通过消息查找的),因此您应该更喜欢方法而不是变量。如果您担心 getter 泄漏信息或 setter 破坏某些不变量,请将它们设为 private .

关于Ruby Mixin 对对象的依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27297392/

相关文章:

javascript - 在 javascript 中访问 Ruby 对象

ruby-on-rails - Rails (ActiveRecord) 多对多表

ruby-on-rails - 如何使用 rails 中的 create 方法创建多个记录并处理验证?

ruby - 如何断言某些方法被 Ruby minitest 框架调用?

ruby - 很难在 Mac 上安装 Ruby

arrays - 删除 Ruby 数组中的重复项

ruby-on-rails - 定义动态类方法

ios - Rubymotion 和结构指针

html - 如何使 Nokogiri 透明地返回未触及/编码的 Html 实体?

javascript - Collection_select 在 javascript 的帮助下使用参数重定向