每个类都直接或间接继承自Object
类。
Object
类具有重要的方法,最常被覆盖:toString
。
问题是:相对于Object
类,这种方法的覆盖是否会导致违反Liskov替代原理?
我将举一个例子。
public class Main
{
public static void main(String[] args)
{
Object o = new Object();
String s = o.toString();
if (s.indexOf('@') > -1) {
System.out.println("OK");
} else {
System.out.println(":-(");
}
}
}
public class MyClass
{
private int x;
public string toString()
{
return Integer.toString(x);
}
}
很明显,如果我将new Object()
替换为new MyClass()
,系统的行为就会改变。
答案 0 :(得分:8)
嗯,这是一个品味问题。 Object
几乎没有保证的属性。因此,也没有什么可违反的。
如果您说返回类名 是可能被侵犯的属性,那么子类当然不应对此进行更改。但是阅读Object.toString()的文档后发现,没有这样的保证:
返回对象的字符串表示形式。通常,toString方法返回一个“以文本形式表示”此对象的字符串。
所以我在这里看不到LSP违规。
LSP并不表示子类的行为必须与超类完全相同。这将使子类完全无用。它只要求子类满足超类的规范。
唯一可以提及的是Object
对每个对象强制执行无意义的方法 toString
。更为复杂的设计可能会将其放入界面中。
我认为,这种设计选择只是一种折衷,也被其他语言(如.NET)所取代。
答案 1 :(得分:1)
Liskov替换原理仅需要接口兼容性。它没有说任何有关基本行为的信息。例如
public interface Text {
String value();
}
public class SimpleText implements Text {
private final String value;
public SimpleText(String value) {
this.value = value;
}
@Override
public String value() {
return this.value;
}
}
public class NumberText implements Text {
private final Number number;
public NumberText(Number number) {
this.number = number;
}
@Override
public String value() {
return String.format("%.3f", this.number.doubleValue());
}
}
您并不关心实现的详细信息,因此可以通过以下方式交换它们:
//We care only about value() method, not its specific implementation
Text text = new SimpleText("text");
text.value();
text = new NumberText(44);
text.value();
答案 2 :(得分:0)
请注意,如果您的实现将引发任何异常,则它将违反LSP,因为Object.toString()不会引发任何异常。