Liskov vs Override - oop

Liskov says : you can't change the super class behaviors in child class.
Override says : you can change the super class behavior in child class.
I am confuse and i don't realize which one is correct?
Thank you for answers

Overriding is a technology. The Liskov Substitution Principle is a rule about how to use that technology. Many programming languages say you can override a method in a child-class, but Barbara Liskov says that you probably shouldn't in most cases.
Keep in mind that the Lisokv Substitution Principle does not say that you must never use override. You just should not use it in a way which causes code intended to work with your base class to not work anymore if it has to work with your child class instead. So if you override a method, you need to ensure that your override still fulfills the contract of the original method.

Related

Reasoning behind open modifier for overriden methods

When overriding a method in Kotlin, the base class defining the method and the method itself must be declared open.
After overriding the method the derived class is final by default, while the overridden method is open by default. From the reference documentation:
A member marked override is itself open, i.e. it may be overridden in subclasses. If you want to prohibit re-overriding, use final.
I wonder why the Kotlin-Team made this design decision instead of making the overridden method final as well, which is the default for the derived class and every non-overriden method. I couldn't find any hint while searching the web?
Does anyone have a link to the reasoning behind this design decision or may motivate it?
It's just much more practical. If the method is open, it means that it's designed to be overridden, and such methods are normally overridden multiple times in a class hierarchy. And marking the derived class as open is much easier than repeating the open modifier for all overridden methods as well.
You could argue that these properties are actually correlating. If the class is explicitly marked as open, all properties and methods which were defined as open are treated the same way in all subclasses. If the subclass is not open, the methods are not overridable, regardless of their own modifiers.
As you might have noticed as well, all modifiers of the original definition are inherited. So you don't have to duplicate that information, only when you want to change the signature, you'll have to define it explicitly.

Does overriding violate the Open/Closed principle?

The open/closed principle states that a class should be open for extension but closed for modification.
I thought that the modification part referred strictly to altering the source code of the base class. But I had an argument with someone saying that this also involves overriding methods from the base class.
It this interpretation correct?
Virtual methods allow replacing behavior of a base class in a derived class, without having to alter the base class and this means you adhere to the Open/Closed principle since you can extend the system without having to modify existing code.
Base classes (that are not purely abstract) however, tend to violate the Dependency Inversion Principle, since the derived class takes a dependency on the base class, which is a concrete component instead of being an abstraction. Remember, the DIP states that:
High-level modules should [...] depend on abstractions.
Besides this, base classes tend to violate the Interface Segregation Principle as well in case they define multiple public (or protected) methods that are not all used by the derived type. This is a violation of the ISP because:
no client should be forced to depend on methods it does not use
"I thought that the modification part referred strictly to altering the source code of the base class."
You thought right.
There is a plethora of ways to make a class extensible and allowing one to inherit from it is one of them. The keyword extend is even used in a few languages to enable inheritance which makes it quite obvious that we aren't modifying, we are extending...
Whether inheritance is the right solution to extensibility or not is another concern, but usually it is not though. Composition should be the preferred way to make classes extensible (e.g. Strategy, Observer, Decorator, Pipes and Filters, etc...)
An override is a lot like a callback that anyone can register. It's like:
if (IsOverridden) CallCallback();
else DefaultImplementation(); //possibly empty
In that sense there is no modification. You are just reconfiguring the object to call the callback instead of doing the default behavior.
It's just like the click event of a button. You wouldn't consider subscribing to an event a modification. It's extension.
Form "Adaptive Code via C#" book, virtual methods is a instrument to achieve OCP.

Does the Liskov Substitution Principle apply to subtype which inherited from abstract class?

loosely speaking, Liskov Substitution Principle states that a derived class can be substitute in place of the base class without affecting the user.
In the case when the base class is an abstract class, which means no user is using an instance of the base class, does the Liskov inheritance restrictions still apply to the derived class?
Just because you can't instantiate a particular class does not mean that you can't use it. In this scenario, the calling code is using the abstract base class as the definition of the contract under which it operates. In that sense, every class that derives from the base class ought to be interchangable with respect to the interface defined by the base class, so yes Liskov still applies. In fact, this is one primary reason why you would want to have an abstract base class for a collection of classes that have some common behavior -- so you can define operations in terms of the base class interface and not care about which derived class that you are actually operating on.
Yes, because a caller can always do this:
BaseAbstractClass instance = new DerivedClass();
Abstract classes do not conflict with LSP at all. Many people consider using "new" directly from the client code to be a violation of the spirit of LSP. If you both instantiate and use an object, you're tightly-bound to that implementation, and you can't "substitute" it at all.
Consider having the object created via a factory or passed in as an argument or via dependency injection after being created by some kind of repository that can be focused on making decisions about what concrete types are needed in various circumstances.
In short, yes. The LSP applies to essentially all public inheritance. The fact that a base class is abstract doesn't change that. The base class defines an interface, and all legitimate derivatives must satisfy all the requirements of that interface.
Yes.
See the "A Real Example" section (page 7-8) of Uncle Bob's The Liskov Substitution Principle article.
Source: the Old Articles page of cleancoder.com

Liskov substitution principle - no overriding/virtual methods?

My understanding of the Liskov substitution principle is that some property of the base class that is true or some implemented behaviour of the base class, should be true for the derived class as well.
I guess this would mean when a method is defined in a base class, it should never be overrided in the derived class - since then substituting the base class instead of the derived class would give different results. I guess this would also mean, having (non-pure) virtual methods is a bad thing?
I think I might have a wrong understanding of the principle. If I don't, I do not understand why is this principle good practice. Can someone explain this to me? Thanks
Subclasses overriding methods in the base class are totally allowed by the Liskov Substituion Principle.
This might be simplifying it too much, but I remember it as "a subclass should require nothing more and promise nothing less"
If a client is using a superclass ABC with a method something(int i), then the client should be able to substitute any subclass of ABC without problems. Instead of thinking about this in terms of variable types, perhaps think about it in terms of preconditions and postconditions.
If our something() method in the ABC base class above has a relaxed precondition that permits any integer, then all subclasses of ABC must also permit any integer. A subclass GreenABC is not allowed to add an additional precondition to the something() method that requires the parameter to be a positive integer. This would violate the Liskov Substitution Principle (i.e., requiring more). Thus if a client is using subclass BlueABC and passing negative integers to something() the client won't break if we need to switch to GreenABC.
In reverse, if the base ABC class something() method has a postcondition - such as guaranteeing it will never return a value of zero - then all subclasses must also obey that same postcondition or they violate the Liskov Substitution Principle (i.e., promising less).
I hope this helps.
There is one popular example which says if it swims like a duck, quack likes a duck but requires batteries, then it breaks Liskov Substitution Principle.
Put it simply, you have a base Duck class which is being used by someone. Then you add hierarchy by introduction PlasticDuck with same overridden behaviors (like swimming, quacking etc.) as of a Duck but requires batteries to simulate those behaviors. This essentially means that you are introducing an extra pre-condition to the behavior of Sub Class to require batteries to do the same behavior that was earlier done by the Base Duck class without batteries. This might catch the consumer of your Duck class by surprise and might break the functionality built around the expected behavior of Base Duck class.
Here is a good link - http://lassala.net/2010/11/04/a-good-example-of-liskov-substitution-principle/
No, it tells that you should be able to use derived class in the same way as its base. There're many ways you can override a method without breaking this. A simple example, GetHashCode() in C# is in base for ALL classes, and still ALL of them can be used as "object" to calculate the hash code. A classic example of breaking the rule, as far as I remember, is derivin Square from Rectangle, since Square can't have both Width and Height - because setting one would change another and thus it's no more conforms to Rectangle rules. You can, however, still have base Shape with .GetSize() since ALL shapes can do this - and thus any derived shape can be substituted and used as Shape.
Overriding breaks Liskov Substitution Principle if you change any behavior defined by a base method. Which means that:
The weakest precondition for a
child method should be not stronger
than for the base method.
A postcondition for the child method
implies a postcondition for the
parent method. Where a postcondition
is formed by: a) all side
effects caused by a method execution and b)
type and value of a returned expression.
From these two requirements you can imply that any new functionality in a child method that does not affect what is expected from a super method does not violate the principle. These conditions allow you to use a subclass instance where a superclass instance is required.
If these rules are not obeyed a class violates LSP. A classical example is the following hierarchy: class Point(x,y), class ColoredPoint(x,y,color) that extends Point(x,y) and overridden method equals(obj) in ColoredPoint that reflects equality by color. Now if one have an instance of Set<Point> he can assume that two points with the same coordinates are equal in this set. Which is not the case with the overridden method equals and, in general, there is just no way to extend an instantiable class and add an aspect used in equals method without breaking LSP.
Thus every time you break this principle you implicitly introduce a potential bug that reveals when invariant for a parent class that is expected by the code is not satisfied. However, in real world often there is no obvious design solution that does not violate LSP, so one can use, for example, #ViolatesLSP class annotation to warn a client that it is not safe to use class instances in a polymorphic set or in any other kind of cases that rely on the Liskov substitution principle.
I think that you're literally correct in the way you describe the principle and only overriding pure virtual, or abstract methods will ensure that you don't violate it.
However, if you look at the principle from a client's point of view, that is, a method that takes a reference to the base class. If this method cannot tell (and certainly does not attempt to and does not need to find out) the class of any instance that is passed in, then you are also not violating the principle. So it may not matter that you override a base class method (some sorts of decorators might do this, calling the base class method in the process).
If a client seems to need to find out the class of an instance passed in, then you're in for a maintenance nightmare, as you should really just be adding new classes as part of your maintenance effort, not modifying an existing routine. (see also OCP)
The original principle:
"What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.".
Barbara Liskov, 1987
The word is behavior. The "preconditions and postconditions" understanding is useful for a good design but is not related to LSP.
Let's check this summary of "preconditions and postconditions" theory:
Don’t implement any stricter validation rules on input parameters than implemented by the parent class.
Apply at the least the same rules to all output parameters as applied by the parent class.
An indication that it has nothing to do with LSP is: what about VOID methods? VOID does not have OUTPUT parameters. How could this rule be applied to VOID methods? How, according to this rule, could we guarantee to be complying with LSP in VOID methods?
LSP refers to Behavior. When a subclass inherits from a superclass and you have to use some trick to make this work, and the result change the behavior of the program you are breaking LSP.
LSP is about behaviour and the clasic example of Square x Rectangle help us to understand. In fact is the example used by Uncle Bob.
The you inherit Square from Rectangle and overrides SetHeight and SetWidth to force Square act as a Square even if it's a rectangle (by inheritance).
When the user calls SetHeight do not expect Width change.... but will change and this change the expected behavior and break LSP.
This is the problem with Virtuals x LSP

Zend_Form and Liskov Substitution Principle

A very common pattern I see (I'm picking on Zend Framework, only because I was dealing with it at the moment of this question), is something like this:
class My_Form extends Zend_Form {
public function init() {
$this->addElement();
}
}
Zend_Form is not an abstract class, but is perfectly usable on its own. This seems to be "recommended" as place to "encapsulate" your forms into a nice class.
Does this violate the Liskov Substitution Principle? Each subclass of Zend_Form will have a wildy different behavior than the base class. Would it be better to use composition for this, or am I totally misunderstanding this principle?
Zend_Form is designed for inheritance. While using Zend_Form everybody should keep that in mind - in reality it is going to be not necessary Zend_Form but may be its subclass. So, if any program relies on Zend_Form to behave exactly as it does, not as its subclass can behave - that program is wrong. It is not "using Base class", as Liskov principle states, it is abusing it.
Zend_Form is used mostly by Zend framework and I'm sure it uses it correctly.
I think for such classes, designed for inheritance and used as build blocks of application based on some framework, definition of "behavior" should be more abstract - leaving some details to subclass, even if class itself is not abstract. I would say that behavior for Zend_Form is "to render some html and use some rules of validation". In this sense all subclasses of Zend_Form behave in the same way. Being Zend_Form non-abstract just defines default behavior which makes it easier to use.
Also to make it a little bit more academic, I could make two classes from it. One should be abstract - base class for all forms. Another one for empty form, that behaves exactly and Zend_Form behaves now and usable on it's own. So it would be something like
// sorry, I don't like PHP so here goes java
public abstract class ZendForm{/*implementation here and NO abstract methods*/}
public final class DefaultZendForm extends ZendForm{/*nothing here*/}
This would remove any confusion about Liskov principle, but ptobably would not add any real value to the program.
Subclass should be different is some way from superclass, otherwise it does not make sense to create subclass. And you always can abuse this difference and write a program that works for superclass and fails for subclass. But it would not be reasonable. Rendering exactly default (empty) form is not a part of Zend_Form's contract. Only behavior that is part of the class contract is a subject for LSP.
Liskov's Substitution Principle states that if a program module is using a Base class, then the reference to the Base class can be replaced with a Derived class without affecting the functionality of the program module.
So how different is MyForm from ZendForm? Would it change the functionality of the program?
Also, check these 2 bullets (from Wikipedia article) :
Preconditions cannot be strengthened in a subclass.
Postconditions cannot be weakened in a subclass.
Perhaps you will find out that MyForm is not so dramatically different from the ZendForm, and you can safely use inheritance.