我有一个子类,它有一个来自超类的额外方法,所以当我需要使用该方法时,我需要强制转换超类。
我想知道这是否违反了对接口的编程?
如果是,那么在超类中实现子类的空方法并在我需要它的子类中重写它会有什么权衡?如果这会使它编程到接口?
答案 0 :(得分:2)
..if this was a violation of programming to an interface?
:是的,绝对。
有关详细信息,请参阅Liskov substitution principle。它如下:
设q(x)是关于类型T的对象x可证明的属性。那么对于S类型的对象y,q(y)应该是可证明的,其中S是T的子类型。
简单的解释可能是这样的:
应该可以通过引用interface
来执行,specific implementation
可以由List<String> violating = new LinkedList<String>();
((LinkedList<String>)violating).addFirst("violating");
完成。如果不可能则违反使用接口的合同。
例如,如果某事完成
List<String> violating
实际上没有必要声明addFirst
,因为它需要使用LinkedList<String> violating
。所以最好在这里使用{{1}}。这应该回答其余的困惑。
答案 1 :(得分:1)
如果一个方法在超类中没有意义,那么在那里添加它只是为了避免强制转换不是一个好主意。如果一个方法在超类中有意义,并且它应该合理地不采取任何操作,那么你应该将该方法放在超类中并在子类中覆盖它。如果添加的方法的功能根本不属于超类,则在子类中添加并实现第二个接口,并在需要其他功能时编程到该接口。
编辑:您可以添加接口WithText
,并将其添加到需要setText
的子类中。如果添加更多需要setText
的子类,请让它们实现该接口。
interface Shape {
void setPosition(int x, int y);
void draw();
}
interface ShapeWithText : Shape {
void setText(string text);
}
class Line implements Shape {
// ...
}
class Circle implements Shape {
// ...
}
class TextBox implements ShapeWithText {
// ...
}
class CircularText implements ShapeWithText {
// ...
}
答案 2 :(得分:1)
至少代码气味。
假设您有class A
和class B extends A
,并且您在课程foo()
中拥有方法B
。现在假设您有一个A
类型的对象,可以一个B
。这在逻辑上意味着,在您的上下文中,您需要类型为A
的对象,而不管超类型。那你为什么要打电话给foo()
?如果您需要通话,为什么不直接在您的上下文中设置B
对象?
我建议您只将foo()
方法放在A
中,当且仅当它在A中有意义时,而不是在B
中覆盖它。
我的猜测是你的设计有缺陷,但也可能不是。在这种情况下,您可以使用instanceof
运算符来确定您的对象是否为B
类型,之后您可以安全地投射。