Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 当遵循Liskov替换原则(LSP)时,子类能否实现额外的接口?_Ruby_Oop_Solid Principles_Liskov Substitution Principle - Fatal编程技术网

Ruby 当遵循Liskov替换原则(LSP)时,子类能否实现额外的接口?

Ruby 当遵循Liskov替换原则(LSP)时,子类能否实现额外的接口?,ruby,oop,solid-principles,liskov-substitution-principle,Ruby,Oop,Solid Principles,Liskov Substitution Principle,考虑这个ruby示例 class Animal def walk # In our universe all animals walk, even whales puts "walking" end def run # Implementing to conform to LSP, even though only some animals run raise NotImplementedError end end class Cat &l

考虑这个ruby示例

class Animal
  def walk
     # In our universe all animals walk, even whales
     puts "walking"
  end

  def run
    # Implementing to conform to LSP, even though only some animals run
    raise NotImplementedError
  end
end

class Cat < Animal
  def run
    # Dogs run differently, and Whales, can't run at all
    puts "running like a cat"
  end

  def sneer_majesticly
    # Only cats can do this. 
    puts "meh"
  end
end
类动物
def步行
#在我们的宇宙中,所有的动物都会行走,即使是鲸鱼
把“行走”
结束
def运行
#执行以符合LSP,即使只有一些动物运行
引发未实现的错误
结束
结束
猫类<动物类
def运行
#狗跑得不一样,鲸鱼根本不能跑
“像猫一样跑”
结束
德夫斯奈尔
#只有猫才能做到这一点。
“嗯”
结束
结束

方法
sneer\u majesticly
是否违反了LSP(仅在Cat上定义),因为该接口在动物身上既不实现也不需要?

LSP说,您可以加入基本类型/接口的任何实现,它应该继续工作。因此,没有理由认为它应该违反这一点,尽管它提出了一些有趣的问题,即为什么您需要在一个实现中而不是在其他实现中实现该附加接口。您是否遵循单一责任原则?

Liskov替换原则与类无关。它是关于类型的。Ruby没有类型作为一种语言特性,所以从语言特性的角度来讨论它们是没有意义的

在Ruby(以及一般的OO)中,类型基本上是协议。协议描述了对象响应的消息以及它如何响应这些消息。例如,Ruby中一个众所周知的协议是迭代协议,它由单个消息
组成,每个
接受一个块,但没有位置或关键字参数,并且
按顺序向块生成
s元素。请注意,没有与此协议对应的类或mixin。对于符合此协议的对象来说,没有办法这样声明

有一个mixin依赖于此协议,即
可枚举
。同样,由于没有与“协议”概念相对应的Ruby构造,
Enumerable
无法声明此依赖关系。仅在(boldemphasis mine)的介绍段落中提到:

Enumerable
mixin为集合类提供了多种遍历和搜索方法,并具有排序功能类必须为每个
提供一个方法,该方法生成集合的连续成员。

就这样

Ruby中不存在协议和类型。它们确实存在于Ruby文档中,存在于Ruby社区中,存在于Ruby程序员的头脑中,存在于Ruby代码中的隐式假设中,但它们从未在代码中体现出来

因此,用Ruby类来谈论LSP没有意义(因为类不是类型),但用Ruby类型来谈论LSP也没有意义(因为没有类型)。您只能根据您头脑中的类型来谈论LSP(因为您的代码中没有任何类型)

好了,结束。但这真的很重要,真的真的很重要。LSP是关于类型的。类不是类型。有C++、java或C语言♯, 如果所有类都是自动类型,但即使在这些语言中,也必须将类型的概念(规则和约束的规范)与类的概念(对象的状态和行为的模板)分开,如果仅仅是因为除了类之外还有其他的东西,它们也是这些语言中的类型(例如Java和C中的接口)♯ 以及Java中的原语),这反过来又来自Smalltalk社区

呸。所以,不幸的是,这些都不能回答你的问题:-D

LSP到底是什么意思?LSP讨论了子类型。更准确地说,它定义了一个(在发明时)基于行为替代性的子类型的新概念。很简单,LSP说:


我可以将T类型的对象替换为S类型的对象。嘲笑是猫的唯一能力。那么,在您看来,为什么它不符合SRP?还是你在暗示我应该使用接口隔离原则?我不认为ISP适用于这里,因为我没有对动物实施嘲笑,只是对猫。我的意思是sneering的内部可以调用另一个类,但它实际上是从Animalife中的其他类中分离出来的。如果你有一些使用动物接口的代码,它就不会知道sneering,也永远不会调用该方法。你这样做的唯一原因是,如果你在其他地方使用Cat,出于其他目的,这意味着Cat有不止一个责任。所以你建议实现一个类Sneer,它接受一个动物,比如Cat,并使它嘲笑?另外,我更新了我的最新评论以及使用动物的代码——我不想让它知道或者能够让动物嘲笑。只有猫才能做到这一点。我从未见过鹦鹉,那会冷笑:-)真的,真的,真的很好的回答。谢谢你,Jorg抽出时间!所以SOLID不能真正应用于Ruby OOP,只能应用于SOID(因为您关于类型的观点)?:-)不,LSP适用于Ruby,我在回答中给出了一个例子。你似乎认为,因为Ruby没有类型,所以类型并不重要。事实并非如此。事实上,在Ruby中,您可能需要比在Scala中更多地考虑类型,因为一切都发生在您的头脑中:类型在程序中不可见,您必须自己记住它们,并且类型不是由语言检查的,您必须自己检查它们。如果某个方法的文档说明存在某个后置条件,而您创建的子类型违反了该后置条件,并且……尝试在程序中使用该子类型的对象,则程序将在运行时崩溃,而崩溃的原因是违反了LSP。在它的底部,LSP会告诉你它什么时候被激活
class Animal
  # …

  # Makes the animal run.
  #
  # @return [void]
  # @raise [NotImplementedError] if the animal can't run
  def run
    raise NotImplementedError
  end
end
class Animal
  # …

  # Animals can't run.
  #
  # @return [never]
  # @raise [NotImplementedError] because animals never run
  def run
    raise NotImplementedError
  end
end