Метод объекта toString и принцип подстановки Лисков

Каждый класс прямо или косвенно наследуется от класса Object.

Класс Object, среди прочих, имеет важный метод, чаще всего переопределяемый: toString.

Вопрос: не приведет ли переопределение этого метода к нарушению принципа подстановки Лискова по отношению к классу Object?

Я сделаю пример.

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(), поведение системы изменится.


person zer0uno    schedule 18.11.2018    source источник
comment
Как вы думаете, почему это нарушает этот принцип?   -  person Eran    schedule 18.11.2018
comment
@Eran Я обновил свой вопрос.   -  person zer0uno    schedule 18.11.2018
comment
@Эран. Вы так и не объяснили, почему считаете, что это нарушает замену.   -  person Mad Physicist    schedule 18.11.2018
comment
@MadPhysicist Замена new Object() на new MyClass() приводит к изменению поведения системы.   -  person zer0uno    schedule 18.11.2018
comment
@нольОуно. Этого следовало ожидать. Если что-то не должно было измениться, зачем вообще создавать подкласс и переопределять? Принцип замещения говорит вам, сколько вы можете изменить, сохраняя при этом совместимость. Опубликованный ответ хорошо справляется с этой поправкой на контракт метода.   -  person Mad Physicist    schedule 18.11.2018
comment
@zer0uno API говорит, что для класса Object возвращаемая строка toString() (короче) является type@hashcode. Это не говорит о том, что так должно быть для вашего класса MyClass или что это требование для метода toString().   -  person Progman    schedule 18.11.2018


Ответы (3)


Ну, это дело вкуса. Object почти не имеет гарантированных свойств. Так что особо нарушать тоже нечего.

Если вы говорите, что возвращение имени класса является таким свойством, которое может быть нарушено, то, конечно, подкласс не должен это менять. Но чтение документации Object.toString() оказывается, что такой гарантии нет:

Возвращает строковое представление объекта. Как правило, метод toString возвращает строку, которая «текстуально представляет» этот объект.

Итак, я не вижу здесь нарушения LSP.

LSP не говорит, что подкласс должен вести себя точно так же, как суперкласс. Это сделало бы подклассы совершенно бесполезными. Требуется только, чтобы подклассы соответствовали спецификации суперкласса.


Единственное, что можно упомянуть, это то, что Object применяет бессмысленный метод toString для каждого объекта. Более сложный дизайн мог бы поместить это в интерфейс.

Я думаю, что этот выбор дизайна является просто компромиссом, принятым и другими языками, такими как .NET.

person Marcel    schedule 18.11.2018

Принцип подстановки Лисков требует только совместимости интерфейсов. Он ничего не говорит о базовом поведении. Так например

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();
person Igor    schedule 18.11.2018

Обратите внимание, что если ваша реализация выдаст какое-либо исключение, то она нарушит LSP, поскольку Object.toString() не выдает никаких исключений.

person oshatrk    schedule 08.11.2019