What is an example of the Liskov Substitution Principle? - oop

I have heard that the Liskov Substitution Principle (LSP) is a fundamental principle of object oriented design. What is it and what are some examples of its use?

A great example illustrating LSP (given by Uncle Bob in a podcast I heard recently) was how sometimes something that sounds right in natural language doesn't quite work in code.
In mathematics, a Square is a Rectangle. Indeed it is a specialization of a rectangle. The "is a" makes you want to model this with inheritance. However if in code you made Square derive from Rectangle, then a Square should be usable anywhere you expect a Rectangle. This makes for some strange behavior.
Imagine you had SetWidth and SetHeight methods on your Rectangle base class; this seems perfectly logical. However if your Rectangle reference pointed to a Square, then SetWidth and SetHeight doesn't make sense because setting one would change the other to match it. In this case Square fails the Liskov Substitution Test with Rectangle and the abstraction of having Square inherit from Rectangle is a bad one.
Y'all should check out the other priceless SOLID Principles Explained With Motivational Posters.

The Liskov Substitution Principle (LSP, lsp) is a concept in Object Oriented Programming that states:
Functions that use pointers or
references to base classes must be
able to use objects of derived classes
without knowing it.
At its heart LSP is about interfaces and contracts as well as how to decide when to extend a class vs. use another strategy such as composition to achieve your goal.
The most effective way I have seen to illustrate this point was in Head First OOA&D. They present a scenario where you are a developer on a project to build a framework for strategy games.
They present a class that represents a board that looks like this:
All of the methods take X and Y coordinates as parameters to locate the tile position in the two-dimensional array of Tiles. This will allow a game developer to manage units in the board during the course of the game.
The book goes on to change the requirements to say that the game frame work must also support 3D game boards to accommodate games that have flight. So a ThreeDBoard class is introduced that extends Board.
At first glance this seems like a good decision. Board provides both the Height and Width properties and ThreeDBoard provides the Z axis.
Where it breaks down is when you look at all the other members inherited from Board. The methods for AddUnit, GetTile, GetUnits and so on, all take both X and Y parameters in the Board class but the ThreeDBoard needs a Z parameter as well.
So you must implement those methods again with a Z parameter. The Z parameter has no context to the Board class and the inherited methods from the Board class lose their meaning. A unit of code attempting to use the ThreeDBoard class as its base class Board would be very out of luck.
Maybe we should find another approach. Instead of extending Board, ThreeDBoard should be composed of Board objects. One Board object per unit of the Z axis.
This allows us to use good object oriented principles like encapsulation and reuse and doesn’t violate LSP.

Substitutability is a principle in object-oriented programming stating that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S
Let's do a simple example in Java:
Bad example
public class Bird{
public void fly(){}
}
public class Duck extends Bird{}
The duck can fly because it is a bird, but what about this:
public class Ostrich extends Bird{}
Ostrich is a bird, but it can't fly, Ostrich class is a subtype of class Bird, but it shouldn't be able to use the fly method, that means we are breaking the LSP principle.
Good example
public class Bird{}
public class FlyingBirds extends Bird{
public void fly(){}
}
public class Duck extends FlyingBirds{}
public class Ostrich extends Bird{}

LSP concerns invariants.
The classic example is given by the following pseudo-code declaration (implementations omitted):
class Rectangle {
int getHeight()
void setHeight(int value) {
postcondition: width didn’t change
}
int getWidth()
void setWidth(int value) {
postcondition: height didn’t change
}
}
class Square extends Rectangle { }
Now we have a problem although the interface matches. The reason is that we have violated invariants stemming from the mathematical definition of squares and rectangles. The way getters and setters work, a Rectangle should satisfy the following invariant:
void invariant(Rectangle r) {
r.setHeight(200)
r.setWidth(100)
assert(r.getHeight() == 200 and r.getWidth() == 100)
}
However, this invariant (as well as the explicit postconditions) must be violated by a correct implementation of Square, therefore it is not a valid substitute of Rectangle.

Robert Martin has an excellent paper on the Liskov Substitution Principle. It discusses subtle and not-so-subtle ways in which the principle may be violated.
Some relevant parts of the paper (note that the second example is heavily condensed):
A Simple Example of a Violation of LSP
One of the most glaring violations of this principle is the use of C++
Run-Time Type Information (RTTI) to select a function based upon the
type of an object. i.e.:
void DrawShape(const Shape& s)
{
if (typeid(s) == typeid(Square))
DrawSquare(static_cast<Square&>(s));
else if (typeid(s) == typeid(Circle))
DrawCircle(static_cast<Circle&>(s));
}
Clearly the DrawShape function is badly formed. It must know about
every possible derivative of the Shape class, and it must be changed
whenever new derivatives of Shape are created. Indeed, many view the structure of this function as anathema to Object Oriented Design.
Square and Rectangle, a More Subtle Violation.
However, there are other, far more subtle, ways of violating the LSP.
Consider an application which uses the Rectangle class as described
below:
class Rectangle
{
public:
void SetWidth(double w) {itsWidth=w;}
void SetHeight(double h) {itsHeight=w;}
double GetHeight() const {return itsHeight;}
double GetWidth() const {return itsWidth;}
private:
double itsWidth;
double itsHeight;
};
[...] Imagine that one day the users demand the ability to manipulate
squares in addition to rectangles. [...]
Clearly, a square is a rectangle for all normal intents and purposes.
Since the ISA relationship holds, it is logical to model the Square
class as being derived from Rectangle. [...]
Square will inherit the SetWidth and SetHeight functions. These
functions are utterly inappropriate for a Square, since the width and
height of a square are identical. This should be a significant clue
that there is a problem with the design. However, there is a way to
sidestep the problem. We could override SetWidth and SetHeight [...]
But consider the following function:
void f(Rectangle& r)
{
r.SetWidth(32); // calls Rectangle::SetWidth
}
If we pass a reference to a Square object into this function, the
Square object will be corrupted because the height won’t be changed.
This is a clear violation of LSP. The function does not work for
derivatives of its arguments.
[...]

I see rectangles and squares in every answer, and how to violate the LSP.
I'd like to show how the LSP can be conformed to with a real-world example :
<?php
interface Database
{
public function selectQuery(string $sql): array;
}
class SQLiteDatabase implements Database
{
public function selectQuery(string $sql): array
{
// sqlite specific code
return $result;
}
}
class MySQLDatabase implements Database
{
public function selectQuery(string $sql): array
{
// mysql specific code
return $result;
}
}
This design conforms to the LSP because the behaviour remains unchanged regardless of the implementation we choose to use.
And yes, you can violate LSP in this configuration doing one simple change like so :
<?php
interface Database
{
public function selectQuery(string $sql): array;
}
class SQLiteDatabase implements Database
{
public function selectQuery(string $sql): array
{
// sqlite specific code
return $result;
}
}
class MySQLDatabase implements Database
{
public function selectQuery(string $sql): array
{
// mysql specific code
return ['result' => $result]; // This violates LSP !
}
}
Now the subtypes cannot be used the same way since they don't produce the same result anymore.

There is a checklist to determine whether or not you are violating Liskov.
If you violate one of the following items -> you violate Liskov.
If you don't violate any -> can't conclude anything.
Check list:
No new exceptions should be thrown in derived class: If your base class threw ArgumentNullException then your sub classes were only allowed to throw exceptions of type ArgumentNullException or any exceptions derived from ArgumentNullException. Throwing IndexOutOfRangeException is a violation of Liskov.
Pre-conditions cannot be strengthened: Assume your base class works with a member int. Now your sub-type requires that int to be positive. This is strengthened pre-conditions, and now any code that worked perfectly fine before with negative ints is broken.
Post-conditions cannot be weakened: Assume your base class required all connections to the database should be closed before the method returned. In your sub-class you overrode that method and left the connection open for further reuse. You have weakened the post-conditions of that method.
Invariants must be preserved: The most difficult and painful constraint to fulfill. Invariants are sometimes hidden in the base class and the only way to reveal them is to read the code of the base class. Basically you have to be sure when you override a method anything unchangeable must remain unchanged after your overridden method is executed. The best thing I can think of is to enforce these invariant constraints in the base class but that would not be easy.
History Constraint: When overriding a method you are not allowed to modify an unmodifiable property in the base class. Take a look at these code and you can see Name is defined to be unmodifiable (private set) but SubType introduces new method that allows modifying it (through reflection):
public class SuperType
{
public string Name { get; private set; }
public SuperType(string name, int age)
{
Name = name;
Age = age;
}
}
public class SubType : SuperType
{
public void ChangeName(string newName)
{
var propertyType = base.GetType().GetProperty("Name").SetValue(this, newName);
}
}
There are 2 others items: Contravariance of method arguments and Covariance of return types. But it is not possible in C# (I'm a C# developer) so I don't care about them.

LSP is necessary where some code thinks it is calling the methods of a type T, and may unknowingly call the methods of a type S, where S extends T (i.e. S inherits, derives from, or is a subtype of, the supertype T).
For example, this occurs where a function with an input parameter of type T, is called (i.e. invoked) with an argument value of type S. Or, where an identifier of type T, is assigned a value of type S.
val id : T = new S() // id thinks it's a T, but is a S
LSP requires the expectations (i.e. invariants) for methods of type T (e.g. Rectangle), not be violated when the methods of type S (e.g. Square) are called instead.
val rect : Rectangle = new Square(5) // thinks it's a Rectangle, but is a Square
val rect2 : Rectangle = rect.setWidth(10) // height is 10, LSP violation
Even a type with immutable fields still has invariants, e.g. the immutable Rectangle setters expect dimensions to be independently modified, but the immutable Square setters violate this expectation.
class Rectangle( val width : Int, val height : Int )
{
def setWidth( w : Int ) = new Rectangle(w, height)
def setHeight( h : Int ) = new Rectangle(width, h)
}
class Square( val side : Int ) extends Rectangle(side, side)
{
override def setWidth( s : Int ) = new Square(s)
override def setHeight( s : Int ) = new Square(s)
}
LSP requires that each method of the subtype S must have contravariant input parameter(s) and a covariant output.
Contravariant means the variance is contrary to the direction of the inheritance, i.e. the type Si, of each input parameter of each method of the subtype S, must be the same or a supertype of the type Ti of the corresponding input parameter of the corresponding method of the supertype T.
Covariance means the variance is in the same direction of the inheritance, i.e. the type So, of the output of each method of the subtype S, must be the same or a subtype of the type To of the corresponding output of the corresponding method of the supertype T.
This is because if the caller thinks it has a type T, thinks it is calling a method of T, then it supplies argument(s) of type Ti and assigns the output to the type To. When it is actually calling the corresponding method of S, then each Ti input argument is assigned to a Si input parameter, and the So output is assigned to the type To. Thus if Si were not contravariant w.r.t. to Ti, then a subtype Xi—which would not be a subtype of Si—could be assigned to Ti.
Additionally, for languages (e.g. Scala or Ceylon) which have definition-site variance annotations on type polymorphism parameters (i.e. generics), the co- or contra- direction of the variance annotation for each type parameter of the type T must be opposite or same direction respectively to every input parameter or output (of every method of T) that has the type of the type parameter.
Additionally, for each input parameter or output that has a function type, the variance direction required is reversed. This rule is applied recursively.
Subtyping is appropriate where the invariants can be enumerated.
There is much ongoing research on how to model invariants, so that they are enforced by the compiler.
Typestate (see page 3) declares and enforces state invariants orthogonal to type. Alternatively, invariants can be enforced by converting assertions to types. For example, to assert that a file is open before closing it, then File.open() could return an OpenFile type, which contains a close() method that is not available in File. A tic-tac-toe API can be another example of employing typing to enforce invariants at compile-time. The type system may even be Turing-complete, e.g. Scala. Dependently-typed languages and theorem provers formalize the models of higher-order typing.
Because of the need for semantics to abstract over extension, I expect that employing typing to model invariants, i.e. unified higher-order denotational semantics, is superior to the Typestate. ‘Extension’ means the unbounded, permuted composition of uncoordinated, modular development. Because it seems to me to be the antithesis of unification and thus degrees-of-freedom, to have two mutually-dependent models (e.g. types and Typestate) for expressing the shared semantics, which can't be unified with each other for extensible composition. For example, Expression Problem-like extension was unified in the subtyping, function overloading, and parametric typing domains.
My theoretical position is that for knowledge to exist (see section “Centralization is blind and unfit”), there will never be a general model that can enforce 100% coverage of all possible invariants in a Turing-complete computer language. For knowledge to exist, unexpected possibilities much exist, i.e. disorder and entropy must always be increasing. This is the entropic force. To prove all possible computations of a potential extension, is to compute a priori all possible extension.
This is why the Halting Theorem exists, i.e. it is undecidable whether every possible program in a Turing-complete programming language terminates. It can be proven that some specific program terminates (one which all possibilities have been defined and computed). But it is impossible to prove that all possible extension of that program terminates, unless the possibilities for extension of that program is not Turing complete (e.g. via dependent-typing). Since the fundamental requirement for Turing-completeness is unbounded recursion, it is intuitive to understand how Gödel's incompleteness theorems and Russell's paradox apply to extension.
An interpretation of these theorems incorporates them in a generalized conceptual understanding of the entropic force:
Gödel's incompleteness theorems: any formal theory, in which all arithmetic truths can be proved, is inconsistent.
Russell's paradox: every membership rule for a set that can contain a set, either enumerates the specific type of each member or contains itself. Thus sets either cannot be extended or they are unbounded recursion. For example, the set of everything that is not a teapot, includes itself, which includes itself, which includes itself, etc…. Thus a rule is inconsistent if it (may contain a set and) does not enumerate the specific types (i.e. allows all unspecified types) and does not allow unbounded extension. This is the set of sets that are not members of themselves. This inability to be both consistent and completely enumerated over all possible extension, is Gödel's incompleteness theorems.
Liskov Substition Principle: generally it is an undecidable problem whether any set is the subset of another, i.e. inheritance is generally undecidable.
Linsky Referencing: it is undecidable what the computation of something is, when it is described or perceived, i.e. perception (reality) has no absolute point of reference.
Coase's theorem: there is no external reference point, thus any barrier to unbounded external possibilities will fail.
Second law of thermodynamics: the entire universe (a closed system, i.e. everything) trends to maximum disorder, i.e. maximum independent possibilities.

Long story short, let's leave rectangles rectangles and squares squares, practical example when extending a parent class, you have to either PRESERVE the exact parent API or to EXTEND IT.
Let's say you have a base ItemsRepository.
class ItemsRepository
{
/**
* #return int Returns number of deleted rows
*/
public function delete()
{
// perform a delete query
$numberOfDeletedRows = 10;
return $numberOfDeletedRows;
}
}
And a sub class extending it:
class BadlyExtendedItemsRepository extends ItemsRepository
{
/**
* #return void Was suppose to return an INT like parent, but did not, breaks LSP
*/
public function delete()
{
// perform a delete query
$numberOfDeletedRows = 10;
// we broke the behaviour of the parent class
return;
}
}
Then you could have a Client working with the Base ItemsRepository API and relying on it.
/**
* Class ItemsService is a client for public ItemsRepository "API" (the public delete method).
*
* Technically, I am able to pass into a constructor a sub-class of the ItemsRepository
* but if the sub-class won't abide the base class API, the client will get broken.
*/
class ItemsService
{
/**
* #var ItemsRepository
*/
private $itemsRepository;
/**
* #param ItemsRepository $itemsRepository
*/
public function __construct(ItemsRepository $itemsRepository)
{
$this->itemsRepository = $itemsRepository;
}
/**
* !!! Notice how this is suppose to return an int. My clients expect it based on the
* ItemsRepository API in the constructor !!!
*
* #return int
*/
public function delete()
{
return $this->itemsRepository->delete();
}
}
The LSP is broken when substituting parent class with a sub class breaks the API's contract.
class ItemsController
{
/**
* Valid delete action when using the base class.
*/
public function validDeleteAction()
{
$itemsService = new ItemsService(new ItemsRepository());
$numberOfDeletedItems = $itemsService->delete();
// $numberOfDeletedItems is an INT :)
}
/**
* Invalid delete action when using a subclass.
*/
public function brokenDeleteAction()
{
$itemsService = new ItemsService(new BadlyExtendedItemsRepository());
$numberOfDeletedItems = $itemsService->delete();
// $numberOfDeletedItems is a NULL :(
}
}
You can learn more about writing maintainable software in my course: https://www.udemy.com/enterprise-php/

Let’s illustrate in Java:
class TrasportationDevice
{
String name;
String getName() { ... }
void setName(String n) { ... }
double speed;
double getSpeed() { ... }
void setSpeed(double d) { ... }
Engine engine;
Engine getEngine() { ... }
void setEngine(Engine e) { ... }
void startEngine() { ... }
}
class Car extends TransportationDevice
{
#Override
void startEngine() { ... }
}
There is no problem here, right? A car is definitely a transportation device, and here we can see that it overrides the startEngine() method of its superclass.
Let’s add another transportation device:
class Bicycle extends TransportationDevice
{
#Override
void startEngine() /*problem!*/
}
Everything isn’t going as planned now! Yes, a bicycle is a transportation device, however, it does not have an engine and hence, the method startEngine() cannot be implemented.
These are the kinds of problems that violation of Liskov Substitution
Principle leads to, and they can most usually be recognized by a
method that does nothing, or even can’t be implemented.
The solution to these problems is a correct inheritance hierarchy, and in our case we would solve the problem by differentiating classes of transportation devices with and without engines. Even though a bicycle is a transportation device, it doesn’t have an engine. In this example our definition of transportation device is wrong. It should not have an engine.
We can refactor our TransportationDevice class as follows:
class TrasportationDevice
{
String name;
String getName() { ... }
void setName(String n) { ... }
double speed;
double getSpeed() { ... }
void setSpeed(double d) { ... }
}
Now we can extend TransportationDevice for non-motorized devices.
class DevicesWithoutEngines extends TransportationDevice
{
void startMoving() { ... }
}
And extend TransportationDevice for motorized devices. Here is is more appropriate to add the Engine object.
class DevicesWithEngines extends TransportationDevice
{
Engine engine;
Engine getEngine() { ... }
void setEngine(Engine e) { ... }
void startEngine() { ... }
}
Thus our Car class becomes more specialized, while adhering to the Liskov Substitution Principle.
class Car extends DevicesWithEngines
{
#Override
void startEngine() { ... }
}
And our Bicycle class is also in compliance with the Liskov Substitution Principle.
class Bicycle extends DevicesWithoutEngines
{
#Override
void startMoving() { ... }
}

The LSP is a rule about the contract of the clases: if a base class satisfies a contract, then by the LSP derived classes must also satisfy that contract.
In Pseudo-python
class Base:
def Foo(self, arg):
# *... do stuff*
class Derived(Base):
def Foo(self, arg):
# *... do stuff*
satisfies LSP if every time you call Foo on a Derived object, it gives exactly the same results as calling Foo on a Base object, as long as arg is the same.

I guess everyone kind of covered what LSP is technically: You basically want to be able to abstract away from subtype details and use supertypes safely.
So Liskov has 3 underlying rules:
Signature Rule : There should be a valid implementation of every operation of the supertype in the subtype syntactically. Something a compiler will be able to check for you. There is a little rule about throwing fewer exceptions and being at least as accessible as the supertype methods.
Methods Rule: The implementation of those operations is semantically sound.
Weaker Preconditions : The subtype functions should take at least what the supertype took as input, if not more.
Stronger Postconditions: They should produce a subset of the output the supertype methods produced.
Properties Rule : This goes beyond individual function calls.
Invariants : Things that are always true must remain true. Eg. a Set's size is never negative.
Evolutionary Properties : Usually something to do with immutability or the kind of states the object can be in. Or maybe the object only grows and never shrinks so the subtype methods shouldn't make it.
All these properties need to be preserved and the extra subtype functionality shouldn't violate supertype properties.
If these three things are taken care of , you have abstracted away from the underlying stuff and you are writing loosely coupled code.
Source: Program Development in Java - Barbara Liskov

An important example of the use of LSP is in software testing.
If I have a class A that is an LSP-compliant subclass of B, then I can reuse the test suite of B to test A.
To fully test subclass A, I probably need to add a few more test cases, but at the minimum I can reuse all of superclass B's test cases.
A way to realize is this by building what McGregor calls a "Parallel hierarchy for testing": My ATest class will inherit from BTest. Some form of injection is then needed to ensure the test case works with objects of type A rather than of type B (a simple template method pattern will do).
Note that reusing the super-test suite for all subclass implementations is in fact a way to test that these subclass implementations are LSP-compliant. Thus, one can also argue that one should run the superclass test suite in the context of any subclass.
See also the answer to the Stackoverflow question "Can I implement a series of reusable tests to test an interface's implementation?"

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
When I first read about LSP, I assumed that this was meant in a very strict sense, essentially equating it to interface implementation and type-safe casting. Which would mean that LSP is either ensured or not by the language itself. For example, in this strict sense, ThreeDBoard is certainly substitutable for Board, as far as the compiler is concerned.
After reading up more on the concept though I found that LSP is generally interpreted more broadly than that.
In short, what it means for client code to "know" that the object behind the pointer is of a derived type rather than the pointer type is not restricted to type-safety. Adherence to LSP is also testable through probing the objects actual behavior. That is, examining the impact of an object's state and method arguments on the results of the method calls, or the types of exceptions thrown from the object.
Going back to the example again, in theory the Board methods can be made to work just fine on ThreeDBoard. In practice however, it will be very difficult to prevent differences in behavior that client may not handle properly, without hobbling the functionality that ThreeDBoard is intended to add.
With this knowledge in hand, evaluating LSP adherence can be a great tool in determining when composition is the more appropriate mechanism for extending existing functionality, rather than inheritance.

The Liskov Substitution Principle
The overridden method shouldn’t remain empty
The overridden method shouldn’t throw an error
Base class or interface behavior should not go for modification (rework) as because of derived class behaviors.

The LSP in simple terms states that objects of the same superclass should be able to be swapped with each other without breaking anything.
For example, if we have a Cat and a Dog class derived from an Animal class, any functions using the Animal class should be able to use Cat or Dog and behave normally.

This formulation of the LSP is way too strong:
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.
Which basically means that S is another, completely encapsulated implementation of the exact same thing as T. And I could be bold and decide that performance is part of the behavior of P...
So, basically, any use of late-binding violates the LSP. It's the whole point of OO to to obtain a different behavior when we substitute an object of one kind for one of another kind!
The formulation cited by wikipedia is better since the property depends on the context and does not necessarily include the whole behavior of the program.

In a very simple sentence, we can say:
The child class must not violate its base class characteristics. It must be capable with it. We can say it's same as subtyping.

Liskov's Substitution Principle(LSP)
All the time we design a program module and we create some class
hierarchies. Then we extend some classes creating some derived
classes.
We must make sure that the new derived classes just extend without
replacing the functionality of old classes. Otherwise, the new classes
can produce undesired effects when they are used in existing program
modules.
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.
Example:
Below is the classic example for which the Liskov's Substitution Principle is violated. In the example, 2 classes are used: Rectangle and Square. Let's assume that the Rectangle object is used somewhere in the application. We extend the application and add the Square class. The square class is returned by a factory pattern, based on some conditions and we don't know the exact what type of object will be returned. But we know it's a Rectangle. We get the rectangle object, set the width to 5 and height to 10 and get the area. For a rectangle with width 5 and height 10, the area should be 50. Instead, the result will be 100
// Violation of Likov's Substitution Principle
class Rectangle {
protected int m_width;
protected int m_height;
public void setWidth(int width) {
m_width = width;
}
public void setHeight(int height) {
m_height = height;
}
public int getWidth() {
return m_width;
}
public int getHeight() {
return m_height;
}
public int getArea() {
return m_width * m_height;
}
}
class Square extends Rectangle {
public void setWidth(int width) {
m_width = width;
m_height = width;
}
public void setHeight(int height) {
m_width = height;
m_height = height;
}
}
class LspTest {
private static Rectangle getNewRectangle() {
// it can be an object returned by some factory ...
return new Square();
}
public static void main(String args[]) {
Rectangle r = LspTest.getNewRectangle();
r.setWidth(5);
r.setHeight(10);
// user knows that r it's a rectangle.
// It assumes that he's able to set the width and height as for the base
// class
System.out.println(r.getArea());
// now he's surprised to see that the area is 100 instead of 50.
}
}
Conclusion:
This principle is just an extension of the Open Close Principle and it
means that we must make sure that new derived classes are extending
the base classes without changing their behavior.
See also: Open Close Principle
Some similar concepts for better structure: Convention over configuration

This principle was introduced by Barbara Liskov in 1987 and extends the Open-Closed Principle by focusing on the behavior of a superclass and its subtypes.
Its importance becomes obvious when we consider the consequences of violating it. Consider an application that uses the following class.
public class Rectangle
{
private double width;
private double height;
public double Width
{
get
{
return width;
}
set
{
width = value;
}
}
public double Height
{
get
{
return height;
}
set
{
height = value;
}
}
}
Imagine that one day, the client demands the ability to manipulate squares in addition to rectangles. Since a square is a rectangle, the square class should be derived from the Rectangle class.
public class Square : Rectangle
{
}
However, by doing that we will encounter two problems:
A square does not need both height and width variables inherited from the rectangle and this could create a significant waste in memory if we have to create hundreds of thousands of square objects.
The width and height setter properties inherited from the rectangle are inappropriate for a square since the width and height of a square are identical.
In order to set both height and width to the same value, we can create two new properties as follows:
public class Square : Rectangle
{
public double SetWidth
{
set
{
base.Width = value;
base.Height = value;
}
}
public double SetHeight
{
set
{
base.Height = value;
base.Width = value;
}
}
}
Now, when someone will set the width of a square object, its height will change accordingly and vice-versa.
Square s = new Square();
s.SetWidth(1); // Sets width and height to 1.
s.SetHeight(2); // sets width and height to 2.
Let's move forward and consider this other function:
public void A(Rectangle r)
{
r.SetWidth(32); // calls Rectangle.SetWidth
}
If we pass a reference to a square object into this function, we would violate the LSP because the function does not work for derivatives of its arguments. The properties width and height aren't polymorphic because they aren't declared virtual in rectangle (the square object will be corrupted because the height won't be changed).
However, by declaring the setter properties to be virtual we will face another violation, the OCP. In fact, the creation of a derived class square is causing changes to the base class rectangle.

Some addendum: I wonder why didn't anybody write about the Invariant , preconditions and post conditions of the base class that must be obeyed by the derived classes.
For a derived class D to be completely sustitutable by the Base class B, class D must obey certain conditions:
In-variants of base class must be preserved by the derived class
Pre-conditions of the base class must not be strengthened by the derived class
Post-conditions of the base class must not be weakened by the derived class.
So the derived must be aware of the above three conditions imposed by the base class. Hence, the rules of subtyping are pre-decided. Which means, 'IS A' relationship shall be obeyed only when certain rules are obeyed by the subtype. These rules, in the form of invariants, precoditions and postcondition, should be decided by a formal 'design contract'.
Further discussions on this available at my blog: Liskov Substitution principle

It states that if C is a subtype of E then E can be replaced with objects of type C without changing or breaking the behavior of the program. In simple words, derived classes should be substitutable for their parent classes. For example, if a Farmer’s son is Farmer then he can work in place of his father but if a Farmer’s son is a cricketer then he can’t work in place of his father.
Violation Example:
public class Plane{
public void startEngine(){}
}
public class FighterJet extends Plane{}
public class PaperPlane extends Plane{}
In the given example FighterPlane and PaperPlane classes both extending the Plane class which contain startEngine() method. So it's clear that FighterPlane can start engine but PaperPlane can’t so it’s breaking LSP.
PaperPlane class although extending Plane class and should be substitutable in place of it but is not an eligible entity that Plane’s instance could be replaced by, because a paper plane can’t start the engine as it doesn’t have one. So the good example would be,
Respected Example:
public class Plane{
}
public class RealPlane{
public void startEngine(){}
}
public class FighterJet extends RealPlane{}
public class PaperPlane extends Plane{}

A square is a rectangle where the width equals the height. If the square sets two different sizes for the width and height it violates the square invariant. This is worked around by introducing side effects. But if the rectangle had a setSize(height, width) with precondition 0 < height and 0 < width. The derived subtype method requires height == width; a stronger precondition (and that violates lsp). This shows that though square is a rectangle it is not a valid subtype because the precondition is strengthened. The work around (in general a bad thing) cause a side effect and this weakens the post condition (which violates lsp). setWidth on the base has post condition 0 < width. The derived weakens it with height == width.
Therefore a resizable square is not a resizable rectangle.

The big picture :
What is Liskov Substitution Principle about ? It's about what is (and what is not) a subtype of a given type.
Why is it so important ? Because there is a difference between a subtype and a subclass.
Example
Unlike the other answers, I won't start with a Liskov Substitution Principle (LSP) violation, but with a LSP compliance. I use Java but it would be almost the same in every OOP language.
Circle and ColoredCircle
Geometrical examples seem pretty popular here.
class Circle {
private int radius;
public Circle(int radius) {
if (radius < 0) {
throw new RuntimeException("Radius should be >= 0");
}
this.radius = radius;
}
public int getRadius() {
return this.radius;
}
}
The radius is not allowed to be negative. Here's a suclass:
class ColoredCircle extends Circle {
private Color color; // defined elsewhere
public ColoredCircle(int radius, Color color) {
super(radius);
this.color = color;
}
public Color getColor() {
return this.color;
}
}
This subclass is a subtype of Circle, according to the LSP.
The LSP states that:
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, "Data Abstraction and Hierarchy", SIGPLAN Notices, 23,5 (May, 1988))
Here, for each ColoredCircle instance o1, consider the Circle instance having the same radius o2. For every program using Circle objects, if you replace o2 by o1, the behavior of any program using Circle will remain the same after the substitution. (Note that this is theoretical : you will exhaust the memory faster using ColoredCircle instances than using Circle instances, but that's not relevant here.)
How do we find the o2 depending on o1 ? We just strip the color attribute and keep the radius attribute. I call the transformation o1 -> o2 a projection from the CircleColor space on the Circle space.
Counter Example
Let's create another example to illustrate the violation of the LSP.
Circle and Square
Imagine this subclass of the previous Circle class:
class Square extends Circle {
private int sideSize;
public Square(int sideSize) {
super(0);
this.sideSize = sideSize;
}
#Override
public int getRadius() {
return -1; // I'm a square, I don't care
}
public int getSideSize() {
return this.sideSize;
}
}
The violation of the LSP
Now, look at this program :
public class Liskov {
public static void program(Circle c) {
System.out.println("The radius is "+c.getRadius());
}
We test the program with a Circle object and with a Square object.
public static void main(String [] args){
Liskov.program(new Circle(2)); // prints "The radius is 2"
Liskov.program(new Square(2)); // prints "The radius is -1"
}
}
What happened ? Intuitively, although Square is a subclass of Circle, Square is not a subtype of Circle because no regular Circle instance would ever have a radius of -1.
Formally, this is a violation of Liskov Substitution Principle.
We have a program defined in terms of Circle and there is no Circle object that can replace new Square(2) (or any Square instance by the way) in this program and leave the behavior unchanged: remember that radius of any Circle is always positive.
Subclass and subtype
Now we know why a subclass is not always subtype. When a subclass is not a subtype, i.e. when there is a LSP violation, the behavior of some programs (at least one) won't always be the expected behavior. This is very frustrating and is usually interpreted as a bug.
In an ideal world, the compiler or interpreter would be able to check is a given subclass is a real subtype, but we are not in an ideal world.
Static typing
If there is some static typing, you are bound by the superclass signature at compile time. Square.getRadius() can't return a String or a List.
If there is no static typing, you'll get an error at runtime if the type of one argument is wrong (unless the typing is weak) or the number of arguments is inconsistent (unless the language is very permissive).
Note about the static typing: there is a mechanism of covariance of the return type (a method of S can return a subclass of the return type of the same method of T) and contravariance of the parameters types (a method of S can accept a superclass of a parameter of the same parameter of the same method of T). That is a specific case of precondition and postcondition explained below.
Design by contract
There's more. Some languages (I think of Eiffel) provide a mechanism to enforce the compliance with the LSP.
Let alone the determination the projection o2 of the initial object o1, we can expect the same behavior of any program if o1 is substituted for o2 if, for any argument x and any method f:
if o2.f(x) is a valid call, then o1.f(x) should also be a valid call (1).
the result (return value, display on console, etc.) of o1.f(x) should be equal to the result of o2.f(x), or at least equally valid (2).
o1.f(x) should let o1 in an internal state and o2.f(x) should let o2 in an internal state so that next function calls will ensure that (1), (2) and (3) will still be valid (3).
(Note that (3) is given for free if the function f is pure. That's why we like to have immutable objects.)
These conditions are about the semantics (what to expect) of the class, not only the syntax of the class. Also, these conditions are very strong. But they can be approximated by assertions in design by contract programming. These assertions are a way to ensure that the semantic of the type is upheld. Breaking the contract leads to runtime errors.
The precondition defines what is a valid call. When subclassing a class, the precondition may only be weakened (S.f accepts more than T.f) (a).
The postcondition defines what is a valid result. When subclassing a class, the postcondition may only be strengthened (S.f provides more than T.f) (b).
The invariant defines what is a valid internal state. When subclassing a class, the invariant must remain the same (c).
We see that, roughly, (a) ensures (1) and (b) ensures (2), but (c) is weaker than (3). Moreover, assertions are sometimes difficult to express.
Think of a class Counter having a unique method Counter.counter() that returns the next integer. How do you write a postcondition for that ? Think of a class Random having a method Random.gaussian() that returns a float between 0.0 and 1.0 . How do you write a postcondition to check that the distribution is gaussian ? It may be possible, but the cost would be so high that we would rely on test rather than on postconditions.
Conclusion
Unfortunately, a subclass is not always a subtype. This can lead to an unexpected behavior -- a bug.
OOP languages provide mechanism to avoid this situation. At syntactic level first. At semantical level too, depending on the programming language: a part of the semantics can be encoded in the text of the program using assertions. But it's up to you to ensure that a subclass is a subtype.
Remember when you began to learn OOP ? "If the relation is IS-A, then use inheritance". That's true the other way: if you use inheritance, be sure that the relation is IS-A.
The LSP defines, at a higher level than assertions, what is a subtype. Assertions are a valuable tool to ensure that the LSP is upheld.

Would implementing ThreeDBoard in terms of an array of Board be that useful?
Perhaps you may want to treat slices of ThreeDBoard in various planes as a Board. In that case you may want to abstract out an interface (or abstract class) for Board to allow for multiple implementations.
In terms of external interface, you might want to factor out a Board interface for both TwoDBoard and ThreeDBoard (although none of the above methods fit).

The clearest explanation for LSP I found so far has been "The Liskov Substitution Principle says that the object of a derived class should be able to replace an object of the base class without bringing any errors in the system or modifying the behavior of the base class" from here. The article gives code example for violating LSP and fixing it.

Let's say we use a rectangle in our code
r = new Rectangle();
// ...
r.setDimensions(1,2);
r.fill(colors.red());
canvas.draw(r);
In our geometry class we learned that a square is a special type of rectangle because its width is the same length as its height. Let's make a Square class as well based on this info:
class Square extends Rectangle {
setDimensions(width, height){
assert(width == height);
super.setDimensions(width, height);
}
}
If we replace the Rectangle with Square in our first code, then it will break:
r = new Square();
// ...
r.setDimensions(1,2); // assertion width == height failed
r.fill(colors.red());
canvas.draw(r);
This is because the Square has a new precondition we did not have in the Rectangle class: width == height. According to LSP the Rectangle instances should be substitutable with Rectangle subclass instances. This is because these instances pass the type check for Rectangle instances and so they will cause unexpected errors in your code.
This was an example for the "preconditions cannot be strengthened in a subtype" part in the wiki article. So to sum up, violating LSP will probably cause errors in your code at some point.

LSP says that ''Objects should be replaceable by their subtypes''.
On the other hand, this principle points to
Child classes should never break the parent class`s type definitions.
and the following example helps to have a better understanding of LSP.
Without LSP:
public interface CustomerLayout{
public void render();
}
public FreeCustomer implements CustomerLayout {
...
#Override
public void render(){
//code
}
}
public PremiumCustomer implements CustomerLayout{
...
#Override
public void render(){
if(!hasSeenAd)
return; //it isn`t rendered in this case
//code
}
}
public void renderView(CustomerLayout layout){
layout.render();
}
Fixing by LSP:
public interface CustomerLayout{
public void render();
}
public FreeCustomer implements CustomerLayout {
...
#Override
public void render(){
//code
}
}
public PremiumCustomer implements CustomerLayout{
...
#Override
public void render(){
if(!hasSeenAd)
showAd();//it has a specific behavior based on its requirement
//code
}
}
public void renderView(CustomerLayout layout){
layout.render();
}

I encourage you to read the article: Violating Liskov Substitution Principle (LSP).
You can find there an explanation what is the Liskov Substitution Principle, general clues helping you to guess if you have already violated it and an example of approach that will help you to make your class hierarchy be more safe.

LISKOV SUBSTITUTION PRINCIPLE (From Mark Seemann book) states that we should be able to replace one implementation of an interface with another without breaking either client or implementation.It’s this principle that enables to address requirements that occur in the future, even if we can’t foresee them today.
If we unplug the computer from the wall (Implementation), neither the wall outlet (Interface) nor the computer (Client) breaks down (in fact, if it’s a laptop computer, it can even run on its batteries for a period of time). With software, however, a client often expects a service to be available. If the service was removed, we get a NullReferenceException. To deal with this type of situation, we can create an implementation of an interface that does “nothing.” This is a design pattern known as Null Object,[4] and it corresponds roughly to unplugging the computer from the wall. Because we’re using loose coupling, we can replace a real implementation with something that does nothing without causing trouble.

Related

OOP: Inheriting from immutable objects

Background
Suppose I have some set of fields which are related to each other I therefore make a class to gather them. Let us call this class Base. There are certain methods as well, which operate on these fields which will be common to all derived classes. Additionally, let us suppose we want Base and all its derived classes to be immutable.
In different contexts, these fields support additional operations, so I have different derived classes which inherit the fields and provide additional methods, depending on their context. Let us call these Derived1, Derived2, etc.
In certain scenarios, the program needs instances of a derived class, but the state of the fields must satisfy some condition. So I made a class RestrictedDerived1 which makes sure that the condition is satisfied (or changes the parameters to conform if it can) in the constructor before calling its base constructor, or throws an error otherwise.
Further, there are situations where I need even more conditions to be met, so I have SuperRestrictedDerived1. (Side note: given that some conditions are met, this class can more efficiently compute certain things, so it overrides some methods of Derived1.)
Problem
So far so good. The problem is that most of the methods of all these classes involve making another instance of some class in this hierarchy (not always the same as the one that the method was called on, but usually the same one) based on itself, but with some modifications which may involve somewhat complex computation (i.e. not just changing one field). For example one of the methods of Derived1 might look like:
public Derived1 foo(Base b) {
TypeA fieldA = // calculations using this and b
TypeB fieldB = // more calculations
// ... calculate all fields in this way
return new Derived1(fieldA, fieldB, /* ... */);
}
But then down the hierarchy RestrictedDerived1 needs this same function to return an instance of itself (obviously throwing an error if it can't be instantiated), so I'd need to override it like so:
#Override
public ResrictedDerived1 foo(Base b) {
return new RestrictedDerived1(super.foo(b));
}
This requires a copy constructor, and unnecessarily allocating an intermediate object which will immediately destroyed.
Possible solution
An alternative solution I thought of was to pass a function to each of these methods which constructs some type of Base, and then the functions would look like this:
// In Derived1
public Derived1 foo(Base b, BaseCreator creator) {
TypeA fieldA = // calculations using this and b
TypeB fieldB = // more calculations
// ... calculate all fields in this way
return creator.create(fieldA, fieldB, /* ... */);
}
public Derived1 foo(Base b) {
return foo(b, Derived1::create);
}
public static Derived1 create(TypeA fieldA, TypeB fieldB, /* ... */) {
return new Derived1(fieldA, fieldB, /* ... */);
}
// In RestrictedDerived1
#Override
public ResrictedDerived1 foo(Base b) {
return (RestrictedDerived1) foo(b, RestrictedDerived1::create);
}
public static RestrictedDerived1 create(TypeA fieldA, TypeB fieldB, /* ... */) {
return new RestrictedDerived1(fieldA, fieldB, /* ... */);
}
My question
This works, however it feels "clunky" to me. My question is, is there some design pattern or concept or alternative design that would facilitate my situation?
I tried do use generics, but that got messy quick, and didn't work well for more than one level of inheritance.
By the way, the actual classes that these refer to is 3D points and vectors. I have a base called Triple with doubles x, y, and z (and some functions which take a lambda and apply them to each coordinate and construct a new Triple with the result). Then I have a derived class Point with some point related functions, and another derived class Vector with its functions. Then I have NonZeroVector (extends Vector) which is a vector that cannot be the zero vector (since other objects that need a vector sometimes need to be guaranteed that it's not the zero vector, and I don't want to have to check that everywhere). Further, I have NormalizedVector (extends NonZeroVector) which is guaranteed to have a length of 1, and will normalize itself upon construction.
MyType
This can be solved using a concept variously known as MyType, this type, or self type. The basic idea is that the MyType is the most-derived type at runtime. You can think of it as the dynamic type of this, but referred to statically (at "compile time").
Unfortunately, not many mainstream programming languages have MyTypes, but e.g. TypeScript does, and I was told Raku does as well.
In TypeScript, you could solve your problem by making the return type of foo the MyType (spelled this in TypeScript). It would look something like this:
class Base {
constructor(public readonly fieldA: number, public readonly fieldB: string) {}
foo(b: Base): this {
return new this.constructor(this.fieldA + b.fieldA, this.fieldB + b.fieldB);
}
}
class Derived1 extends Base {
constructor(fieldA: number, fieldB: string, protected readonly repeat: number) {
super(fieldA * repeat, fieldB.repeat(repeat));
}
override foo(b: Base): this {
return new this.constructor(
this.fieldA + b.fieldA, this.fieldB + b.fieldB, this.repeat
);
}
}
class RestrictedDerived1 extends Derived1 {
constructor(fieldA: number, fieldB: string, repeat: number) {
super(fieldA * repeat, fieldB.repeat(repeat), repeat);
if (repeat >= 3) {
throw new RangeError(`repeat must be less than 3 but is ${repeat}`)
}
}
}
const a = new RestrictedDerived1(23, 'Hello', 2);
const b = new Base(42, ' World');
const restrictedDerived = a.foo(b); // Inferred type is RestrictedDerived1
Slightly b0rken Playground link
Implicit factories
In a language with type classes or implicits (like Scala), you could solve your problem with implicit Factory objects. This would be similar to your second example with the Creators, but without the need to explicitly pass the creators around everywhere. Instead, they would be implicitly summoned by the language.
In fact, your requirement is very similar to one of the core requirements of the Scala Collections Framework, namely that you want operations like map, filter, and reduce to only be implemented once, but still preserve the type of the collection.
Most other Collections Frameworks are only able to achieve one of those goals: Java, C#, and Ruby, for example, only have one implementation for each operation, but they always return the same, most-generic type (Stream in Java, IEnumerable in C#, Array in Ruby). Smalltalk's Collections Framework is type-preserving, but has duplicated implementations for every operation. A non-duplicated type-preserving Collections Framework is one of the holy grails of abstractions designers / language designers. (It's no coincidence that so many papers that present novel approaches to OO uses a refactoring of the Smalltalk Collection Framework as their working example.)
F-bounded Polymorphism
If you have neither MyType nor implicit builders available, you can use F-bounded Polymorphism.
The classic example is how Java's clone method should have been designed:
interface Cloneable<T extends Cloneable<T>> {
public T clone();
}
class Foo implements Cloneable<Foo> {
#Override
public Foo clone() {
return new Foo();
}
}
JDoodle example
However, this gets tedious very quickly for deeply-nested inheritance hierarchies. I tried to model it in Scala, but I gave up.

'this' is not defined in this context

How can I solve the following case?
interface I
class A(i: I)
class C : I, A(this) // << --- 'this' is not defined in this context
In short, I want to pass the class instance to super class constructor.
Is it possible in Kotlin?
P.S.
All the answers are good and technically correct. But let's give a concrete example:
interface Pilot {
fun informAboutObstacle()
}
abstract class Car(private val pilot: Pilot) {
fun drive() {
while (true) {
// ....
if (haveObstacleDetected()) {
pilot.informAboutObstacle()
}
// ....
}
}
fun break() {
// stop the car
}
}
class AutopilotCar : Pilot, Car(this) { // For example, Tesla :)
override fun informAboutObstacle() {
break() // stop the car
}
}
This example don't look too contrived, and why can't I implement it with OOP-friendly language?
No, this is not possible on the JVM. this is only available after the super class has been initialized.
From
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.10.2.4
The instance initialization method (§2.9.1) for class myClass sees the new uninitialized object as its this argument in local variable 0. Before that method invokes another instance initialization method of myClass or its direct superclass on this, the only operation the method can perform on this is assigning fields declared within myClass.
So the bytecode instruction aload 0 to push this on the stack is forbidden before the super-class constructor is called. That's why it cannot be passed as an argument to the super-constructor.
Kotlin was born as a JVM language and aims for maximum interoperability with Java code and a minimum overhead of its language features. While Kotlin could have chosen to orchestrate object initialization in a different way, it would create problems in mixed Java-Kotlin class hierarchies and add significant overhead.
In the good tradition of OOP languages such as Java, C# or Swift, Kotlin doesn't allow you to leak the this reference before the call to superclass initialization has completed. In your special case you're just storing the reference, but in just a slightly different case the superclass code might try to use the received object, which at that point is still uninitialized.
As a specific example of why languages don't allow this, consider a case where A is a class from a library you use and this rule is not in effect. You pass this like you do and things work fine. Later you update the library to a newer version and it happens to add something as benign as i.toString() to its constructor. It has no idea it's actually calling an overridden method on itself. Your toString() implementation observes all its invariants broken, such as uninitialized vals.
This design suffers from other problems, not just the circular initialization dependency you are struggling with now. In a nutshell, the class A expects this:
But instead you create this:
The class A has a dependency on a collaborator object of type I. It doesn't expect itself as the collaborator. This may bring about all kinds of weird bugs. For example your C.toString() may delegate to super.toString() and A.toString() (A is the super of C) may call into I.toString(), resulting in a StackOverflowError.
I can't say from your question whether A is designed for extension, which would make the C : A part correct, but you should definitely disentangle A from I.

How does the CLR know which method to call on a derived class inherited from an abstract base?

I have the following situation and I was wondering how the CLR knows which method to call:
public abstract class Shape
{
public abstract String PrintName();
}
public sealed class Square : Shape
{
public override String PrintName() { return "Square"; }
}
public sealed class Circle : Shape
{
public override String PrintName() { return "Circle"; }
}
So then I instantiate each shape:
Shape square = new Square();
Shape circle = new Circle();
List<Shape> shapes = new List<Shape> { square, circle };
foreach (Shape s in shapes)
{
Console.WriteLine(s.PrintName());
}
// Output:
// Square
// Circle
So how is it that we can call the method on the derived class even though we are calling the method on the base type? I'm confused how this is handled.
Because of the type safety feature of the CLR, which ensures that when you create an instance of Foo you cannot treat it as Bar, at run time it always knows what type an object is. Therefore when you call PrintName() on your shape it knows if it is dealing with a Square or a Circle.
Note, that as GetType() is non virtual it cannot be overridden and therefore you cannot spoof an object's type.
When you instantiate Shape square = new Square();, the fact that square really is a Square really is intact. Remember that the variable square really is a reference to the real object. The reference type (in this case, Shape) must be the same class or higher up the inheritance hierachy than the instantiated type (Square), as you have here.
After instantiation, when the compiler sees square, it first knows that it's the abstract type Shape because that's the type of the reference. So, it must be a sub-type of Shape since you can't instantiate an abstract object. Since you said new Square(); the compiler will know the exact type. Again, the exact type of an object is not lost just because you assigned it to a baser (more base) type.
When you call square.PrintName();, the compiler first sees that square is declared with the abstract type Shape, who has a method PrintName(), also marked abstract. This tells the compiler to go look for the same exact method in the child class. If it finds PrintName() in the child class, all is well - the correct function will be executed. If not, you get an error because the word abstract in the base class definition requires you to implement it.

Reducing the number of arguments to a constructor

I am reading "Clean Code" and having trouble figuring out how to keep some of my functions (usually constructors) to their MAXIMUM of 3 parameters.
Often my objects need an awful lot of information to work - am I supposed to make a small constructor and then use mutator functions to give them all of the information? This doesn't seem any better than just using a big constructor.
As an example, I have a "MovablePatch" class. It lets the user drag a square around in a window. It needs a several parameters, including Radius, Color, Renderer, InitialPosition, and Visibility. Currently I collect all of these from my GUI and then call:
MovablePatch(int radius, Renderer* renderer, Color color, Position initial, bool visibility)
These are only some of the things that I need in this class. Can anyone suggest how else I might package this information to pass to the constructor? I don't see any obvious "break it into smaller classes" appearing here.
You could have
MovablePatch(Renderer* renderer, CircleAppearance circleAppearance)
where CircleAppearance gathers the other info.
However, clean code and other books that generalize about what good code should look like, are aiming for 80 percent of the code out there. Your code seems to be "closer to the metal" than the typical LoB (Line of Business) variety. As such, you may run into places where certain coding ideals are not applicable.
The most important part is that you're thinking about it and trying to keep things nice and tidy! :)
Do not take maxims like "thou shalt not have more than 3 parameters in thy constructors" at face value. If you have the slightest chance of making an object immutable, make it; and if it being immutable means that it is going to have a constructor with 50 parameters, so be it; go for it; don't even think about it twice.
Even if the object is going to be mutable, still, you should pass its constructor as many parameters as necessary so that immediately upon construction it will be in a valid and meaningful state. In my book, it is absolutely impermissible to have to know which are the magic mutator methods that have to be called (sometimes even in the right order) before any other methods can be invoked, under penalty of segfault.
That having been said, if you would really like to reduce the number of parameters to a constructor, or to any function, simply pass this method an interface that it can invoke to get from it the stuff it needs in order to work.
Some of the things you are passing in could be abstracted into a larger construct. For example, visibility, color, and radius, could make sense to be placed into an object that you define. Then, an instance of this class, call it ColoredCircle, could be passed into the constructor of MovablePatch. A ColoredCircle doesn't care where it is or what renderer it is using, but a MovablePatch does.
My main point, is that from an OO perspective, radius isn't really an integer, it's a radius. You want to avoid these long constructor lists because it is daunting to understand the context of these things. If you collect them into a larger class, kind of like how you already have with Color and Position, you can have fewer parameters passed in and make it easier to understand.
The Named Parameter Idiom is useful here. In your case, you might have
class PatchBuilder
{
public:
PatchBuilder() { }
PatchBuilder& radius(int r) { _radius = r; return *this; }
PatchBuilder& renderer(Renderer* r) { _renderer = r; return *this; }
PatchBuilder& color(const Color& c) { _color = c; return *this; }
PatchBuilder& initial(const Position& p) { _position = p; return *this; }
PatchBuilder& visibility(bool v) { _visibility = v; return *this; }
private:
friend class MovablePatch;
int _radius;
Renderer* _renderer;
Color _color;
Position _position;
bool _visibility;
};
class MovablePatch
{
public:
MovablePatch( const PatchBuilder& b ) :
_radius( b._radius );
_renderer( b._renderer );
_color( b._color );
_position( b._position );
_visibility( b._visibility );
{
}
private:
int _radius;
Renderer* _renderer;
Color _color;
Position _position;
bool _visibility;
};
then you use it like so
int
main()
{
MovablePatch foo = PatchBuilder().
radius( 1.3 ).
renderer( asdf ).
color( asdf ).
position( asdf ).
visibility( true )
;
}
overly simplified, but I think it gets the point across. If certain parameters are required they can be included in the PatchBuilder constructor:
class PatchBuilder
{
public:
PatchBuilder(const Foo& required) : _foo(required) { }
...
};
Obviously this pattern degenerates into the original problem if all arguments are required, in which case the named parameter idiom isn't applicable. The point being, this isn't a one size fits all solution, and as Adam describes in the comment below there are additional costs and some overhead with doing so.
One good option is to use a Builder pattern, where each "setter" method returns the own instance, and you can chain the methods as you need.
In your case, you will get a new MovablePatchBuilder class.
The approach is very useful and you can find it in many different frameworks and languages.
Refer here to see some examples.

What is an abstract data type in object oriented programming?

What is an abstract data type in object oriented programming? I've gone through the wiki for this topic, but I am still unclear about it. Could someone clarify?
An abstract class is a generalization concept. It is a class you invent to only use as a base class for inheritance but not to instantiate objects from.
And abstract datatype (ADT) is not necessarily an OOP concept. It is an older term to describe the concepts of for example Stack and Queue in terms of their functionality, without describing the implementation.
There is a difference between an "abstract data type" and an "abstract class".
An abstract class is one that may not have definitions for all the methods it defines. You therefore cannot directly instantiate an abstract class. You have to create a subclass and then instantiate that.
An abstract data type is a model of a certain kind of data structure e.g. a Stack. A Stack has push() and pop() operations and that have well-defined behaviour.
The abstract data type (ADT) itself refers to this model, not any particular implementation in any particular programming language or paradigm. You could implement a Stack in an object-oriented language, but you could also implement it in a functional programming language.
ADTs allow discussion about the properties of Stacks, Queues etc that hold for all correct implementations of the ADT.
Well, it's all about abstraction. Abstraction is particularly useful in programming. The main advantage is ability to hide realization details. You hide it inside one modules (so-called "server modules") and provide some public interface for other modules (so-called "client modules"). And now we have three different possibilities:
Server module can supply an abstract data structure (ADS) itself.
In that case it contains ADS entity itself. The public interface consists of some procedures (and maybe some constants).
Interface of server module (stack_ads.h):
#ifndef STACK_ADS
#define STACK_ADS
const int capacity = 10;
void clear();
int size();
int pop();
void push(int value);
#endif STACK_ADS
Implementation (stack_ads.cpp):
#include "stack_ads.h"
int items[capacity];
int top = -1;
void clear()
{
top = -1;
}
int size()
{
return top + 1;
}
int pop()
{
top -= 1;
return items[top + 1];
}
void push(int value)
{
top += 1;
items[top] = value;
}
In the client module (main.cpp) we import server module and use data structure directly.
#include <iostream>
#include "stack_ads.h"
int main (int argc, char* const argv[])
{
push(1);
push(2);
push(3);
std::cout << pop() << std::endl;
std::cout << pop() << std::endl;
std::cout << pop() << std::endl;
return 0;
}
Server module can supply an abstract data type (ADT) in the form of struct/record.
In client module we can declare variables to be of that type. Because a module is free to declare more than one variable to be of the exported type, it can have more than one data structure. Each abstract data structure is variable of abstract data type.
Interface (stack_adt.h):
#ifndef STACK_ADT
#define STACK_ADT
const int capacity = 10;
typedef struct
{
int items[capacity];
int top;
} StackADT;
void clear(StackADT* stack);
int size(StackADT* stack);
int pop(StackADT* stack);
void push(StackADT* stack, int value);
#endif STACK_ADT
Implementation (stack_adt.cpp):
#include "stack_adt.h"
void clear(StackADT* stack)
{
stack->top = -1;
}
int size(StackADT* stack)
{
return stack->top + 1;
}
int pop(StackADT* stack)
{
stack->top -= 1;
return stack->items[stack->top + 1];
}
void push(StackADT* stack, int value)
{
stack->top += 1;
stack->items[stack->top] = value;
}
Client module:
#include <iostream>
#include "stack_adt.h"
int main (int argc, char* const argv[])
{
StackADT stack1;
StackADT stack2;
stack1.top = -1;
stack2.top = -1;
push(&stack1, 1);
push(&stack1, 2);
push(&stack1, 3);
std::cout << pop(&stack1) << std::endl;
std::cout << pop(&stack1) << std::endl;
std::cout << pop(&stack1) << std::endl;
push(&stack2, 10);
push(&stack2, 20);
push(&stack2, 30);
std::cout << pop(&stack2) << std::endl;
std::cout << pop(&stack2) << std::endl;
std::cout << pop(&stack2) << std::endl;
return 0;
}
Finally the server module can supply an abstract data type (ADT) in the form of class.
If our language support OOP we can describe ADT by means of classes. And once again in client module we can declare variables to be of that type. In object-oriented terminology, the type is called a class, and the variable with that type is called an object.
Server module interface (Stack.h):
#ifndef STACK
#define STACK
const int capacity = 10;
class Stack
{
public:
Stack();
void clear();
int size();
int pop();
void push(int value);
private:
int items[capacity];
int top;
};
#endif STACK
Implementation (Stack.cpp):
#include "Stack.h"
Stack::Stack()
{
this->top = -1;
}
void Stack::clear()
{
this->top = -1;
}
int Stack::size()
{
return this->top + 1;
}
int Stack::pop()
{
this->top -= 1;
return this->items[this->top + 1];
}
void Stack::push(int value)
{
this->top += 1;
this->items[this->top] = value;
}
The differences between two last options are:
Terminological mentioned above (type <-> class, variable <-> object).
In the non-class ADT, the formal parameter list of every procedure must include a variable s of type Stack. In the stack class, the specification of the data structure s is not included with the other formal parameters following the name of the procedure, but
stands alone enclosed in parentheses before the name of the procedure. Using Smalltalk terminology formal parameter before the procedure name is called the receiver.
The location of the procedures. In the non-class ADT, the procedures are located outside the Stack struct. In the class, the procedures are located within the class. In object-oriented terminology, procedures that have receivers, and are therefore contained within a class type, are called methods.
Client code:
#include <iostream>
#include "stack.h"
int main (int argc, char* const argv[])
{
Stack stack1;
Stack stack2;
stack1.push(1);
stack1.push(2);
stack1.push(3);
std::cout << stack1.pop() << std::endl;
std::cout << stack1.pop() << std::endl;
std::cout << stack1.pop() << std::endl;
stack2.push(10);
stack2.push(20);
stack2.push(30);
std::cout << stack2.pop() << std::endl;
std::cout << stack2.pop() << std::endl;
std::cout << stack2.pop() << std::endl;
return 0;
}
An Abstract Data Type (ADT) is a mathematical model of a type of data. It describes operations that can be performed on the data and the mathematical definition of those operations using equations.
For example, you can model the behaviour of a stack of numbers, perfectly abstractly using operations such as pop(), push(), top() and maybe a constant symbol representing the empty stack.
For example here are some equations that could form part of the definition of a stack of numbers:
pop(empty) = empty // silently ignores popping an empty stack
pop(push(N,S)) = S // i.e. pop removes the top element of push(N,S)
top(push(N,S)) = N // return topmost element of the stack without changing the stack
An abstract data type isn't at all the same thing as a class in an object model - although they bare some similarities.
Here are the names of the important concepts: initial algebra semantics, isomorphism, quotients, congruences
The point of an abstract data type is to understand the behaviour of a whole class of equivalent type representations using equations and some fancy mathematics that demonstrates that each implementation is "isomorphic" - i.e. that both implementations are exactly equivalent as far as the observable behaviour is concerned.
The wikipedia entry on this is pretty good: http://en.wikipedia.org/wiki/Abstract_data_type
Here are some good (but very theoretical) course notes that pin down what an ADT is http://www-compsci.swan.ac.uk/~csulrich/ftp/adt/adt.pdf
Although superficially similar to the concept of a "class" in some object-oriented programming languages, a "class" is not an ADT, but a class can be used to implement a specific ADT.
In general the ADT concept is probably more applicable to functional programming than object-oriented programming because not all object-oriented programming languages have classes and ADT-style thinking produces less effective OO designs.
Here's a paper that demonstrates the problems of thinking in terms of ADTs in an OO language: http://portal.acm.org/citation.cfm?id=74885
Basically the paper shows that the "class" that you use to implement an ADT ends up covered with lots of tiny little methods (that look like the basis of ADT equations) rather than having a few powerful, high-abstraction methods.
Definition:
Roughly speaking, Abstract Data Type (ADT) is a way of looking at a data structure: focusing on what it does and ignoring how it does its job.
Abstract data types are defined primarily by their interface: the permissible operations that can be carried out on them. The underlying mechanism used to
implement them is typically not visible to their user.
Examples:
Stack, Queue and PriorityQueue are some of the examples of the ADTs, they are more abstract than say arrays, linked lists and many other data storage structures.
For example, the underlying mechanism for a stack, can be an Array or it can be a LinkedList. The underlying mechanism for a PriorityQueue can be an Array or a special kind of tree called a Heap.
Code:
Here is a Java example of the abstract data type called PriorityQueue, implemented using the Heap:
class Heap {
private Node heapArray[];
public void insert(Node node) {...}
public Node remove() {...}
}
class PriorityQueue {
private Heap heap;
public void insert(Node node) {
heap.insert(node);
}
public Node remove() {
return heap.remove();
}
}
Here you can see that the methods for the PriorityQueue class are simply wrapped around the methods for the underlying Heap class. Similarly you can use Array instead of Heap to implement the same functionality, even though in case of Array you'll need more code to take care of operations like insert and remove. This example should make it conceptually clear that a PriorityQueue is an ADT that can be implemented in a variety of ways, using heap, arrays and so on.
Although, ADTs make more sense in object oriented programming (OOP) languages, they are not limited to only OOP languages and can also be created using non-OOP languages.
In the school they taught me that an ADT is just a group which contains a collection of data, and a set of operations that can be taken over this data. It just refers to the idea, and is not related with any ,language, implementation neither paradigm.
Updated:
so re-reading the question, and accordingly to mi definition, an abstract data type in OOP should be a class abstraction, inherited or not, because it contains data (properties, fields, etc) and operations (methods).
regards
Abstract is most fundamental and generalized concept in a programming and real life.
What is an abstract data type in object oriented programming?
ADT is a container which holds different types of objects with specifications. logical representation(i.e an interface or protocol) of the data and the operations to manipulate the component elements of the data.
Examples of ADT: List, Map, Set, Stack, Queue, Tree, Graph.
Data structures can implement one or more particular abstract data types (ADT). In java for example ArrayList, LinkedList, Stack and Vector are data structures implementation(classes) of List.
Stack examples in real life:
When a person wear bangles the last bangle worn is the first one to
be removed and the first bangle would be the last to be removed.
This follows last in first out (LIFO) principle of stack.
In a stack of plates, once can take out the plate from top or can
keep plate at the top. The plate that was placed first would be the
last to take out. This follows the LIFO principle of stack.
Batteries in the flashlight :- You cant remove the second battery
unless you remove the last in. So the battery that was put in first
would be the last one to take out. This follows the LIFO principle
of stack.
Clothes in the trunk
queue examples in real life
A queue of people at ticket-window: The person who comes first gets the ticket first. The person who is coming last is getting the tickets in last. Therefore, it follows first-in-first-out (FIFO) strategy of queue.
Vehicles on toll-tax bridge: The vehicle that comes first to the toll tax booth leaves the booth first. The vehicle that comes last leaves last. Therefore, it follows first-in-first-out (FIFO) strategy of queue.
Luggage checking machine: Luggage checking machine checks the luggage first that comes first. Therefore, it follows FIFO principle of queue.
Patients waiting outside the doctor's clinic: The patient who comes first visits the doctor first, and the patient who comes last visits the doctor last. Therefore, it follows the first-in-first-out (FIFO) strategy of queue.
The above examples collected from Source1 and Source2
Take one step back from the code:
What does abstract mean?
Abstract
The gist of it is "not real, but capturing a property of real things"
You need to know this for OOP because you will be designing object universes, which requires you to think about how those objects are related.
Abstraction allows you to group some of those objects, thus organizing
1) Your thinking process
2) Your code
I had the same problem until last week.
An abstract class is something that is common or something in general. You can use that class to mould it and extend it in anyway you like.
I can give you a practical example here
Take a class called animal. And it contains functions like eat, sound, move which is general that all animals do. You can extend that class to get specific like cats, dogs etc.
eg.
abstract class animal {
abstract protected function eat();
abstract protected function sound();
}
class dogs extends animal
{
protected function eat() {
return "meat";
}
public function sound() {
return "bow wow";
}
}
hope my answer made sense to you
classes uses the concept of data abstraction , known as absract data type .
abstract data type is an older term to describe the concepts of stack and queues in terms of their functionality without describing their implementation .
Abstract Data Type (ADT) is a mathematical model with a collection of operations defined on that model.
Also, ADT is a data type whose behavior is defined by set of values and set of operations.
Shortly: abstract means that you can't make objects from the defined class. ex: if you have shape,square and rectangle classes, but you don't want to define any objects from shape so you will mark it as abstract...
after that if the user try to define a new object from shape, he will got compiler error..
This is from Code Complete -Quote:
Abstract data types form the foundation for the concept of classes. In lanuages that support classes, you can implement each abstract data type in its own class. Classes usually involve the additional concepts of inheritance and polymorphism. One way of thinking of a class is as an abstract data type plus inheritance and polymorphism.
So in my opinion, Abstract data type in OO means abstract class.
What is an abstract data type in object oriented programming?
A Class/Abstract data type is a group of properties, and functions
(for accessing data) of anything which we may want to deal with
while solving some problem in an object oriented way.
What is an object?
Object is an interface to a Class/Abstract data type through which we can access its properties and functions. Objects have memories associated with them used for storing data.
An ADT defines a set of data values and a set of operations on these values.
From this post:
ADT is a set of objects and operations, no where in an ADT’s definitions is there any mention of how the set of operations is implemented. Programmers who use collections only need to know how to instantiate and access data in some pre-determined manner, without concerns for the details of the collections implementations. In other words, from a user’s perspective, a collection is an abstraction, and for this reason, in computer science, some collections are referred to as abstract data types (ADTs). The user is only concern with learning its interface, or the set of operations its performs.
Object such as lists, sets and graphs along with their operations can be viewed as abstract data types. ADTs are basically data types that hides its implementation details. Any part of a program that needs to perform an operation on ADT can do so by merely changing the routines that performs the ADT operations. The program that use them (ADT) will not necessarily need to know which implementation was used
ADT is a kind of data structure. Instead of describing the structure of data, it describes the operation on the data.
For example, what is a stack? Maybe a search tree or some linear data structure, but the user doesn't care. The user just cares about "last in first out" (LIFO).
It is just like an interface. Abstract data type in a class is just used to define something i.e. Without body/implementation such as abstract methods. The body will be added where that class will be inherited.
The difference between interface and Abstract class is that we can not add a method with body in interface where as in abstract class, we can add methods/variables with body/value or make it abstract(i.e. Define there and implement where it is overrided).
An abstract class does not form a concrete object in the real world unlike pure implementation classes. Abstract as the name suggestes they hold/define common behaviours of related objects that need to be reused/defined independantly in all related objects.
Take an example of Birds. If you are writing a progrm that will have something to do with the birds, then you'll first have an abstract base class as Bird and each bird deriving from the abstract base class Bird. Do note that abstract class BIRD does not represent a concrete real world object but a type of related objects that is birds!
Lets start with the class-diagram and then some code.
alt text http://ruchitsurati.net/files/birds.png
public abstract class Bird
{
protected string Name = string.Empty;
public Bird(string name)
{
this.Name = name;
}
public virtual void Fly()
{
Console.WriteLine(string.Format("{0} is flying.", this.Name));
}
public virtual void Run()
{
Console.WriteLine(string.Format("{0} cannot run.", this.Name));
}
}
public class Parrot : Bird
{
public Parrot() : base("parrot") { }
}
public class Sparrow : Bird
{
public Sparrow() : base("sparrow") { }
}
public class Penguin : Bird
{
public Penguin() : base("penguin") { }
public override void Fly()
{
Console.WriteLine(string.Format("{0} cannot fly. Some birds do not fly.", this.Name));
}
public override void Run()
{
Console.WriteLine(string.Format("{0} is running. Some birds do run.", this.Name));
}
}
class Program
{
static void Main(string[] args)
{
Parrot p = new Parrot();
Sparrow s = new Sparrow();
Penguin pe = new Penguin();
List<Bird> birds = new List<Bird>();
birds.Add(p);
birds.Add(s);
birds.Add(pe);
foreach (Bird bird in birds)
{
bird.Fly();
bird.Run();
}
Console.ReadLine();
}
}
Abstract type means whose objects does not exist in real world since it does not have
physical entity.
It acts as a base class for concrete class which has physical existance.
e.g.
Shape is an abstract class whereas circle,rectangle are concrete classes.