Object orientation is an interesting and powerful way of designing, modeling and creating not just applications but also business models and just about anything. Here I’ll explain the basics.
Classes and objects
Instead of creating insubstantial and vague procedures and functions with extensive flow control to create the best spaghetti meal in town, objects allow the creation on concrete, close-to-the-real-world things (called objects) which are classified according to what they know and how they behave.
A Bicycle, for example, can change its gear, accelerate, break and steer. It has information on how many gears it has and what its speed and heading is.
Everything in an object oriented world is an object and each object is classified and therefore is an instance of a certain class. A class describes what behaviour and information an object of said class has, and each object of that class then has that information and behaviour.
Continuing with the Bicycle example, we could create two instances of class Bicycle, which can be called objects of class Bicycle. The first object could be heading north at a speed of 10 km/h on its 3rd gear, while the second one is stopped, facing east, on gear 1. Both of these objects have the same information (heading, speed, gear), but the individual values are different and can change over time. As the second bike starts moving, its speed increases, and at some point it will probably change to a higher gear. An object can also have information that is specified when the object is created. The color of the bicycle, for example, doesn’t change very often.
- A single entity that is a collection of (depending on your viewpoint):
- data and code (binary perspective)
- variables and methods (source code perspective)
- information and services (design perspective)
- state and behaviour (analysis perspective)
- A definition of what information and services a certain type of object has. Every object is an instance of some class.
Generalization and inheritance
When you start defining classes for our system, you’ll quickly find out, that you have several classes that are slightly different but have meny things in common. In that case you can take advantage of class inheritance and define a superclass that has the common information and several subclasses that add to the superclass’s definition.
If we add motorcycles to the system in addition to the bicycles, we have two classes that are different, yet in many ways similar. Let’s define a superclass Vehicle that has behaviour such as accelerate, break and steer, and information on its speed and heading. We’ll then specify that class Bicycle inherits or extends Vehicle, and has additional behaviour such as changing the gear. The class Motorcycle will also inherit Vehicle and has additional behaviour like changing the gear, starting the engine and shutting down the engine, and it will also have additional information, such as the amount of petrol left in the tank.
- A class that has subclasses.
- A class that inherits all the information and behaviour from one or more superclasses. A subclass can have additional information and can have additional behaviour, or override some of the superclasses’ behaviour.
One of the key features of OO is information hiding and encapsulation. Information hiding means that the information an object has is hidden from the outside, so it cannot be changed or even looked at. The only way to get the value of a piece of information is to call a method that gives out that information. Similarly, to change a value, you have to call a method that will do that for you. A method is another (more programming oriented) name for a service. An object’s behaviour is made up of its services, or methods.
Encapsulation concerns the object’s methods. Only the signature of the method is visible to the outside. The signature shows how that particular method can be used. However, what the method actually does when it is invoked, is not shown. This has quite powerful ramifications. The greatest advantage is that the method’s contents can be changed freely at any time and as long as the signature stays the same, the change will not affect any other part of the system. In traditional programming styles a change somewhere can easily break the system in a dozen other places. Encapsulation makes sure that no part of the system is dependent of a class’s inner implementation, which makes updates and bug corrections significantly easier.
Do not confuse information hiding with security. Information hiding does not protect the data in any way, but is simply there at compile time to make sure that the developers don’t directly use an object’s internal data from the outside, but do it via appropriate method calls.
- Storage place for one piece of information. A variable has a type, which tells what the information is (a number, a string, an array, a GearBox…) and a name, which is used at the source code level to handle the variable.
- A piece of code that can be called (invoked). Calling a method executes the code it contains. A method can accept parameters which it can then use in its code. A method can return a single value of some type, which the caller can use after the call is complete.
- Every method has a signature, which defines the method’s name, its visibility (who is allowed to call it), the parameters it requires and the type of value it returns. The signature contains all the information needed to make sure that the method is called in an appropriate way, but contains no reference of what the method actually does.
Polymorphism is another powerful feature of object orientation. By definition it means that any object of a certain class C can be treated as if it were an object of any superclass of class C. This is quite natural, since a subclass always inherits all the information and behaviour of its superclasses. This means that an object of that class will have all the methods and variables that the superclasses’ objects need to have, and therefore it can be thought of and treated as an instance of any of those superclasses.
If we create several Bicycle objects and Motorcycle objects, they are different and have different services, but they all contain the methods defined in the superclass Vehicle. Therefore we can treat these objects as Vehicles if needed. We can, for example, create a Vehicle array and store all the Bicycles and Motorcycles there. We can further iterate through the array and tell all the Vehicles to brake and turn to the right. If we later want to differentiate between Bicycles and Motorcycles, we can check the exact class of each object.
If a subclass overrides some of its superclasses methods, then the new methods (defined in the subclass) are used instead of the superclass’s methods. However, when the object is being treated as an instance of the superclass (as in the example) and an overriden method is called, two things could happen: 1) the subclass’s method is called, or 2) the superclass’s method is called. So which will happen? Object orientatied languages have a word for this: virtual methods. If a method is declared virtual, then all overrides are effective, and whenever a method is called, the actual class of the object is checked and the subclass’s version of the method is called. If a method is non-virtual, then the method defined in the class that the object is treated as will be called. Using non-virtual methods is a potential source of bugs, but virtual methods have a higher overhead, which makes method virtualization a performance issue. C++ methods are by default non-virtual, and Java methods are always virtual.
Abstract classes and methods
To be added later.
This concludes my short introduction to object orientation.
Hopefully it has been useful to you. I would definitely like to hear any
comments you have