对象toString方法和Liskov替换原理

时间:2018-11-18 13:34:01

标签: java liskov-substitution-principle

每个类都直接或间接继承自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(),系统的行为就会改变。

3 个答案:

答案 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()不会引发任何异常。