为什么Ruby人说他们不需要接口?

Hap*_*per 8 ruby oop interface

ruby与其他OOP语言有什么不同(例如:PHP)会使接口变得无用吗?它有什么替代品吗?

编辑:

一些澄清:

  • 在其他语言(例如:PHP)中,您不需要"接口"(在代码级别它们不是必需的).您可以使用它们签订合同,以改进软件的架构.因此,肯定'在红宝石中你不需要接口/在其他语言中你需要接口因为XXX'是假的.

  • 不,mixins不是接口,它们是完全不同的东西(PHP 5.4实现了mixins).你有没有使用过接口?

  • 是的,PHP是OOP.语言不断发展,欢迎来到现在.

Jul*_*lik 15

嗯,这是一个共识,当一个对象在Ruby中传递时,它不是经过类型检查的.在Java和PHP接口是肯定的对象符合一定的合同或"类型"的方式(这样的东西可能是Serializable,Authorizable,Sequential以及任何你想要的其他东西).

但是,在Ruby中,没有形式化合同的概念,接口将履行一些有意义的角色,因为方法签名中没有检查接口一致性.例如,见Enumerable.当您将其混合到对象中时,您正在使用其功能,而不是声明您的对象Enumerable.让你的对象存在的唯一好处Enumerable就是已经定义了each(&blk)你自动获取map,select而朋友则是免费的.你可以完美地拥有一个实现所提供的所有方法的对象,Enumerable但不会在模块中混合,它仍然可以工作.

例如,对于Ruby中需要IO对象的任何方法,您可以提供与IO 无关的内容,然后它会因错误而爆炸,或者 - 如果您正确实现了IO存根 - 它将正常工作即使您传递的对象未被声明为"IO-ish".

这背后的想法来自这样一个事实:Ruby中的对象并不是真正美化的哈希表,并且标签被打到它们上(然后有一些额外的标签告诉解释器或编译器该对象具有接口X因此它可以用于上下文Y)但是一个响应消息的封闭实体.因此,如果一个对象响应一个特定的消息,它会填充合同,如果它没有响应该消息 - 那么就会出现错误.

因此缺少接口可以部分地通过模块的存在来补偿(模块可以包含您在不对呼叫者/消费者做出任何类型承诺的情况下达到的功能),部分地由消息传递的传统而不是类型化的dicts来补偿.

你应该观看Jim Weirich的一些演讲,因为他广泛接触这个主题.


Nie*_* B. 5

这个问题有点开放,但这是我的看法:

接口声明的目的有两个:

  1. 向你未来的自己或同事声明这个类必须有哪些方法
  2. 向您的计算机声明该类必须具有哪些方法

如果我们首先考虑第二个目的,Ruby 源代码永远不会被编译,因此永远没有选项来验证与接口声明的一致性并警告开发人员任何不符合的情况。这意味着,如果 Ruby 有一些内置的接口支持,它在运行时之前不会有验证一致性的选项,因为缺少实现,应用程序无论如何都会崩溃。

所以回到第一个目的。代码可读性。这可能有意义,指定接口的正式 Ruby 约定可能会有所帮助。现在,您可能会使用评论或规范或 - 正如我可能更喜欢的 - 声明性模块包含来传达这一点。例如

module Shippable
# This is an interface module. If your class includes this module, make sure it responds to the following methods

  # Returns an integer fixnum representing weight in grams
  def weight
    raise NotImplementedError.new
  end

  # Returns an instance of the Dimension class.
  def dimensions
    raise NotImplementedError.new
  end

  # Returns true if the entity requires special handling.
  def dangerous?
    raise NotImplementedError.new
  end

  # Returns true if the entity is intended for human consumption and thereby must abide by food shipping regulations.
  def edible?
    raise NotImplementedError.new
  end

end

class Product
  include Shippable
end
Run Code Online (Sandbox Code Playgroud)

强制执行此接口的一种方法是创建一个规范,该规范创建包含该Shippable模块的每个类的实例,调用四个方法并期望它们不会 raise NotImplementedError


Jef*_*Day 0

我相信这是因为 Ruby 是动态类型的,而其他语言是静态类型的。您需要在 PHP 中使用接口的唯一原因是在传递对象时使用类型提示。