Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Java array covariance violate Liskov Substitution Principle?

I was reading why array covariance in Java is bad (Why are arrays covariant but generics are invariant?). If a Dog is a subtype of Animal, then a Dog[] is a subtype of Animal[]. This is a problem because things like this can be done:

Animal[] animals = new Dog[1];
animals[0] = new Cat();

This is different from generics which were implemented 'correctly'. A List<Dog> is not a subtype of List<Animal>

I was trying to understand the essence of why it is bad and had just read about LSP. Did it violate the LSP in any way? There doesn't seem to be a clear violation.

like image 666
Lee Kang Avatar asked Mar 06 '17 22:03

Lee Kang


People also ask

What violates Liskov Substitution Principle?

A very common violation of this principle is the partial implementation of interfaces or base class functionality, leaving unimplemented methods or properties to throw an exception (e.g. NotImplementedException).

What is the most accurate example of the Liskov Substitution Principle in OOP?

A good example here is that of a bird and a penguin; I will call this dove-penguin problem. The below is a Java code snippet showing an example that violates the LSP principle. Here, the Dove can fly because it is a Bird. In this inheritance, much as technically a penguin is a bird, penguins do not fly.

Which OOP principle is absolutely important for the Liskov Substitution Principle?

The Open/Closed Principle To understand the Liskov Substitution Principle, we must first understand the Open/Closed Principle (the “O” from SOLID). The goal of the Open/Closed principle encourages us to design our software so we add new features only by adding new code.

Which statement best describes the Liskov Substitution Principle?

The Liskov Substitution Principle states that subclasses should be substitutable for their base classes.


1 Answers

Did it violate the LSP in any way?

Yes.

There doesn't seem to be a clear violation.

Your own example is a violation. The following code works fine:

Animal[] animals = new Animal[1];
animals[0] = new Cat();

But if now replace the Animal[] with its subtype Dog[], the code no longer works (that is, it causes an exception when it didn't previously). So the type Dog[] can't be used everywhere where its supertype Animal[] can be used and that violates the LSP.

To put this in the LSP's wording: If we consider the property "new Cat() can be assigned as an element", the type Animal[] fulfils this property, but its subtype Dog[] does not.

like image 120
sepp2k Avatar answered Oct 02 '22 22:10

sepp2k