zer0uno
zer0uno

Reputation: 8030

Object toString method and Liskov substitution principle

Every class, directly or indirectly, inherits from the Object class.

The Object class, among the others, has the important method, most often overridden: toString.

The question is: doesn't the overriding of this method bring to Liskov Substitution Principle violation with respect to the Object class?

I'll do an example.

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);
    }
}

Obviously if I replace new Object() with new MyClass() the behavior of the system changes.

Upvotes: 0

Views: 332

Answers (3)

oshatrk
oshatrk

Reputation: 529

Note that if your implementation will throw any exception then it will violate LSP as Object.toString() doesn't throw any exceptions.

Upvotes: 0

Binary Igor
Binary Igor

Reputation: 168

Liskov substitution principle requires only interface compatibility. It does not say anything about underlying behavior. So for example

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());
    }
}

You do not care about details of implementation, so you can exchange them this way:

//We care only about value() method, not its specific implementation
Text text = new SimpleText("text");
text.value();
text = new NumberText(44);
text.value();

Upvotes: 1

Marcel
Marcel

Reputation: 1855

Well, it's a matter of taste. Object has almost no guaranteed properties. So there is no much to violate either.

If you say that returning the class name is such a property that may be violated, then of course, a subclass should not change this. But reading the documentation of Object.toString() turns out that there is no such guarantee:

Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object.

So I see no LSP violation here.

LSP does not say that a subclass must behave exactly the same as the superclass. This would make subclasses entirely useless. It only requires that subclasses meet the specification of the superclass.


The only thing one could mention is that Object enforces a meaningless method toString for every object. A more sophisticated design might have put this into an interface.

I think this design choice is just a compromise, taken over by other languages like .NET as well.

Upvotes: 8

Related Questions