空接口(抽象类),用于对象的逻辑分组,以避免LSP违规

Woo*_*Moo 1 language-agnostic polymorphism design-patterns

在现实世界中,正方形是一个矩形,但对于程序而言,情况并非如此(LSP原理).它是否被认为是一种反模式/差编程来创建一个空白接口来逻辑地将对象组合在一起?我的想法是一个空白的界面,它不可能违反LSP它下面的水平.下面举例说明.

Abstract class Canine{ }  

Dog extends Canine {…} 

Wolf extends Canine {…}
Run Code Online (Sandbox Code Playgroud)

Ste*_*sop 6

取决于它的用途.

空接口没有强加语法要求,因为没有方法可以实现.

但是接口可能被记录在案施加语义的要求,尤其是当Canine自己从继承CanoideaCarnivora或什么的.这使得空接口可能有用,因为它提供了自己的保证.所有的食肉目都有耳朵[*],但是Canoidea的部分特征是耳朵的某些属性不容易表达为添加方法,因此实现界面成为一个承诺:"除了作为食肉目之外,我的耳朵表现得像那样".

这意味着违反LSP不再是不可能的.您可能会意外地编写一个带有重写函数的子类,该函数返回12,这是Carnivora允许的,但是Canine的语义表示它不会返回超过10.

只添加语义的接口不一定很好用,因为它有一些容易犯的错误.一个例子是C++ 之间InputIterator和之间的区别ForwardIterator(当然这些是模板概念,而不是继承的接口).如果用错误的类标记您的类,编译器将永远不会注意到.但是如果你用RandomAccessIterator什么时候标记你的类ForwardIterator,那么当有人试图使用它时,编译器注意到operator+,因为它operator+是RandomAccessIterator的一部分而不是ForwardIterator.

没有语义的空接口是没有意义的,因此可能没用.我能想到的唯一用途是作为一种变体 - 一些狡猾的代码可以测试对象是否是"狗"或"狼"(或其他)的实例,并相应地做不同的事情.这可能不是一个好用途,因为它可能首先不是好的代码.你可以使用最终的超类Object,如果可用的话,因为代码必须处理它无法识别和无法处理的类型."究竟什么是福克斯,我不能在这里使用福克斯"并不比"什么是矢量,我不能在这里使用矢量"更好或更糟,所以如果你理解的是狗和狼,接受一个Canine与接受一个相比没有真正的优势Object.它们都是允许Dogs,Wolves以及其他任何人选择插入层次结构的变体.

[*]是的,甚至海豹.他们只是没有耳廓.