質問

I have a model abstract class which declares a List of items. The abstract has two abstract class. One in which you can add new items to the list and one that doesn't use the list at all but adheres otherwise to the other behavior of the model abstract class.

I declared two methods to add and remove items from the list. Obviously, whenever I want to use those methods I need to cast my model abstract with its subclass.

Can I violate LSP (Liskov substitution principle) in this case? Or is there a way around this problem?

役に立ちましたか?

解決

I think you will violate LSP.

From the Wikipedia page for LSP (that is always your friend ;):

"More formally, the Liskov substitution principle (LSP) is a particular definition of a subtyping relation, called (strong) behavioral subtyping"

"Behavioral subtyping is a stronger notion than typical subtyping of functions defined in type theory, which relies only on the contravariance of argument types and covariance of the return type. Behavioral subtyping is trivially undecidable in general"

Looks similar to your case:

"A typical example that violates LSP is a Square class that derives from a Rectangle class, assuming getter and setter methods exist for both width and height. The Square class always assumes that the width is equal with the height. If a Square object is used in a context where a Rectangle is expected, unexpected behavior may occur because the dimensions of a Square cannot (or rather should not) be modified independently. This problem cannot be easily fixed: if we can modify the setter methods in the Square class so that they preserve the Square invariant (i.e., keep the dimensions equal), then these methods will weaken (violate) the postconditions for the Rectangle setters, which state that dimensions can be modified independently. Violations of LSP, like this one, may or may not be a problem in practice"

他のヒント

Never studied LSP but ill say this

Having to cast is always a sign of bad( less optimal) OO design.

If you want a Model that you can set things too then declare it as the correct model

same goes for the Java Collection API

Collection coll = new ArrayList();
((List) coll).set(3,"sdf");

Is code that will work but is just badly written

should have offcourse been

List coll = new ArrayList();
coll.set(3,"sdf");

use the specific type for what you want

I understand LSP, but here it might be that the problem addresses the design reason that java has single inheritance and multiple interfaces.

One class can extend just one other class. In C++ this was not the case and there could be conflicting names in the super classes. Multiple inheritance gave some theoretical type problems too.

So you have to turn one aspect into an interface, and extend from an abstract class implementing one or more interfaces maybe.

LSP holds when Square extends from Rectangle and implements WidthEqualsHeight.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top