接口(或所有方法抽象的抽象类)是 C#、JAVA 等静态类型语言的有力武器。它允许以统一的方式使用不同的派生类型。设计模式鼓励我们尽可能多地使用接口。
但是,在动态类型语言中,不会在编译时检查所有对象的类型。他们不必实现以特定方式使用的接口。您只需要确保它们定义了一些方法(属性)。这使得接口不是必需的,或者至少不像静态语言那样有用。
典型的动态语言(例如 ruby)是否有接口?如果有,那么拥有它有什么好处?如果不是这样,那么我们是否会失去许多需要界面的精美设计模式?
谢谢。
接口(或所有方法抽象的抽象类)是 C#、JAVA 等静态类型语言的有力武器。它允许以统一的方式使用不同的派生类型。设计模式鼓励我们尽可能多地使用接口。
但是,在动态类型语言中,不会在编译时检查所有对象的类型。他们不必实现以特定方式使用的接口。您只需要确保它们定义了一些方法(属性)。这使得接口不是必需的,或者至少不像静态语言那样有用。
典型的动态语言(例如 ruby)是否有接口?如果有,那么拥有它有什么好处?如果不是这样,那么我们是否会失去许多需要界面的精美设计模式?
谢谢。
我想所有动态语言都没有单一的答案。例如,在 Python 中,没有接口,但有多重继承。使用类接口类仍然有用:
isinstance(x, SomeType)
,尤其是当SomeType
包含许多方法时。动态语言中的接口作为 API 文档非常有用,可以自动检查,例如通过开发工具或在运行时断言。
例如,zope.interface是 Python 中接口的事实标准。诸如 Zope 和 Twisted 等公开大量 API 以供消费使用的项目发现它很有用,但据我所知,它在此类项目之外使用得不多。
在 Ruby 中,这是一种动态类型语言,只允许单继承,您可以通过 mixins 来模拟“接口”,而不是用“接口”的方法污染类。
Mixin 部分模拟了多重继承,允许一个对象从多个源“继承”,但没有实际拥有多个父级的模糊性和复杂性。只有一位真正的父母。
要实现一个接口(在抽象意义上,而不是像静态类型语言中的实际接口类型),您将模块定义为就好像它是静态语言中的接口一样。然后,您将其包含在课程中。瞧!您已经将鸭子类型收集到本质上是一个界面的内容中。
非常简化的例子:
module Equippable
def weapon
"broadsword"
end
end
class Hero
include Equippable
def hero_method_1
end
def hero_method_2
end
end
class Mount
include Equippable
def mount_method_1
end
end
h = Hero.new
h.weapon # outputs "broadsword"
m = Mount.new
m.weapon # outputs "broadsword"
Equippable 是 Hero、Mount 和任何其他包含它的类或模型的接口。
(显然,武器很可能由初始化程序动态设置,在本例中已被简化。)