Up Home Blog About

Object Oriented Programming

Tags: software

About classes and objects

In object oriented programming, everything is represented by a class. One single instance of such a representation is called an object.

For example, in Python, I can define a class Car as follows:

class Car():
    """This class represents a car.
    """

    def __init__(self,id):
        self.id = function(guid())

For example, if I have the class Car and I want to instantiate an object MyCar of that class, I would do in Python:

MyCar = Car()

The SOLID principles

A class should obey the SOLID principles. They are:

  • Single Responsibility Principle (SRP)
  • Open-Closed Principle (OCP)
  • Liskov Substitution Princple (LSP)
  • Interface Segregation Principle (ISP)
  • Dependency Injection Principle (DIP)

And they are explained below.

Single Responsibility Principle (SRP)

A class should have only one reason to change. [Uncle Bob]

A class should have one responsibility. In the designed system behaviour and hence also in the software specification. In the latter, a change in the class should have one change in the documentation.

So, one such responsibility may be:

  • the representation of a User, in a User class
  • the representation of an underlying Entity, in an Entity class
  • the representation of a Device
  • the representation of a Car, in the running example

This is related to the Separation of Concerns rule, that has been described by Edsger W. Dijkstra. See for the overlap and differences a nice explanation SRP vs SoC. With the definition of Robert C. Martin (Uncle Bob) - "A class should have only one reason to change" - the SRP narrows down to classes/objects. More abstractly, the Separation of Concerns also holds for the imperative to design an application in units fulfilling different functions.

Open-Closed Principle (OCP)

Classes should be open for extension, but closed for modification. That is, one should be able to extend the behaviour of the class, without modifying the class.

Liskov Substitution Princple (LSP)

"Derived classes must be substitutable for their base classes." codeproject
"Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program" solid wiki
"Functions that use pointers or references to base classes must be able to use object of derived classes without knowing it." source?

If S is a subtype of T, then objects of type T may be replaced with objects of type S. Id est, an object of type T may be substituted with any object of a subtype S without altering any of the desirable properties of T.

Let f(x) be a property provable (true!) for objects x of type T, then f(y) should be true for for objects y of type S where S is a subtype of T.

x(T) has p(x), then y(S(T)) has p(y)

In words: supposed I have a class Vehicle and a subclass Car, then a statement about Vehicles can be replaced with the same statement about Cars:
- A Vehicle is a transportation device; a Car is a transportation device.
The opposite is not necessarily true:
- This Car has an engine; this Vehicle does not necessarily have an engine.

Be careful of the difference between inheritance and subtyping. The latter establishes an is-a relationship and inheritance only reuses implementation and establishes a syntactic relationship, not necessarily a semantic relationship (inheritance does not ensure behavioral subtyping). To distinguish these concepts, subtyping is also known as interface inheritance, whereas inheritance as defined here is known as implementation inheritance or code inheritance. See also: wiki inheritance.

Interface Segregation Principle (ISP)

"Many client specific interfaces are better than one general purpose interface" solid wiki
"Make fine grained interfaces that are client specific." codeproject

Dependency Injection Principle (DIP)

One should depend on abstractions, not on concretions

Techniques

  • Encapsulation (information hiding)
  • Inheritance (subclassing)
  • Abstraction
  • Polymorphism

Inheritance

Composition over inheritance

Composition over inheritance (or composite reuse principle) in object-oriented programming is the principle that classes should achieve polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) rather than inheritance from a base or parent class. (see wiki)

In other words, it is better to compose what an object can do (HAS-A) than extend what it is (IS-A).

Running Example 1.1
class Vehicle():
    def __init__(self,id):
        self.id = function(guid())


class Car(Vehicle):
    """This class represents a car.
    """

    def __init__(self,id):
        self.id = function(guid())

    def method(self):
        return some_function(self)

    def position(self,metric,time)
        return {metric,time}

    def speed(self,time=datetime.now, deltatime=eps):
        return (position(time)-position(time-deltatime))/deltatime

After definition (and inclusion in the namespace of this definition), an object of this class can be instantiated in the program flow. For example, when I want to instantiate an object MyCar from the class Car, I would write:

MyCar = Car()

Now I can access the available methods and properties:

print MyCar.id

Would result in:

>>> print MyCar.id
1

Now let's have a position of the car, based on a (measurement of a temporal) input metric and time:

pos = MyCar.position(0,1)
>>> print pos
set([0,1])