I am responsible for training a bunch of supercharged coders on the basics of the technologies that we use.
A few years ago, when designing the OOPs training module for them, we brainstormed on how should it be done. We thought about this and converged at the same point – To be really effective with OOPs, you must simplify it first. An old interview by the legendary Steve jobs reaffirmed our belief. So we do not start with a programming language. Rather, we chose to use the English language (or any other commonly spoken language) – we all were already better in OOPs there.
Lets see how:
A Cow is an Animal
It has four legs and one tail
“is an” (or “is a”) implies that a Cow would possess all the attributes of an Animal.
This also means that A Cow is a subtype of Animal.
Hence Animal are a much larger type.
There would be many other subtypes of Animals such as a Dog, Buffalo etc.
Animals breathe, eat, move around, make sounds etc
Now since Dog is an Animal and Cow is also an Animal, so both possess these common properties – eating, moving around, making sounds etc.
So is Dog also a Cow?
No.
Why not?
Because both have uncommon properties too. A Cow “moos”, but a dog “barks”.
So,
Animal has properties common to all animals
Cow has properties of Animal == Cow inherits (extends) from Animal
Dog has properties of Animal == Dog inherits (extends) from Animal
Cow makes a mooing sound
Dog makes a barking sound
We just created a class Animal, Dog and Cow.
Do we expect most or all subtypes of Animals to make some sort of sound?
Yes.
Dogs are good at guarding (beware of them!). Cows are not.
Do we expect most or all subtypes of animals to have guarding attributes?
No.
Now let us also define a Buffalo class too:
Buffalo extends Animal { }
Oh, we forgot to add the “sound” for the Buffalo. We were expecting all Animals to make sound, but all of a sudden we have muted all Buffaloes !
We would not have made this mistake if the following English statement could be represented in OOPs too.
If Buffalo is an Animal, then it must makeSound
We can actually represent that in OOPs
Animal { makeSound(); }
Good, now when writing the class Animal what logic should we write in the body of the method “makeSound()”?
We can’t. We don’t know what sound will the actual Animal make. So we leave it to Dog and Cow to make their own sound.
- How?
- Won’t the compiler complain of a missing implementation?
- What would happen if we create the instance of Animal and call makeSound()?
Now OOPs makes that simple too. Mark the method somehow so that the the English examiner (the compiler) knows:
- That some subtype will provide the actual implementation
- Compiler should kinda just ignore the missing implementation of makeSound in Animal
- Compiler shouldn’t allow me to create an instance of Animal. This is just like saying
“There can’t be an Animal which isn’t either a Cat or Dog or Buffalo or… whatever. It has to be something”
English gives us a nice word from the vocabulary to do just that – abstract
It means: existing in thought or as an idea but not having a physical or concrete existence (ref: http://www.oxforddictionaries.com/definition/english/abstract). Thats exactly what makeSound() is for an Animal – it doesn’t have a concrete existence, not until the Dog, Cow or Buffalo come and provide it.
All OOP languages follow suite.
Animal {
breathes
moves around
eats
abstract makeSound();
}
Cow extends Animal { makeSound() { “mooooo”; } }
Dog extends Animal { makeSound() { “bhow bhow”; } }
Now if we forget to implement Buffalo again without allowing it make sound, then the English examiner (our dear compiler) is going to complain
Buffalo extends Animal { }
Compiler Error: Buffalo must implement the abstract method makeSound(). Your are not getting away with it this time !
So we edit it to:
Buffalo extends Animal { makeSound() { “grunt...”; // Psst: I actually googled it } }
Now the Compiler is happy.
Recall that “There can’t be an Animal which isn’t either a Cat or Dog or Buffalo or… whatever. It has to be something”. So we can simply mark the Animal class itself as abstract
abstract Animal { breathes moves around eats abstract makeSound(); }
All this was going well until the Mr X and Mr Y came looking for their cows, which they had allowed to wander for grazing.
Cows? Plural? But did we not just create only one dog, one cow and one buffalo?
What do we provide Mr X and Mr Y with?
Its simple. What we created so far was just describing the cow – that its an animal, what sound does it make. It wasn’t an actual cow !
For an actual cow, or a dog or a buffalo, just instantiate them so that we have their object.
Note that instantiate is frequently interchanged with construction. Object is frequently interchanged with instance.
Now each time we instantiate a Cow, there is one more Cow. Gradually there would be many many cows that exhibit the same behaviour
The Principles of OOPs design – E-D-A-M
If you’ve understood the above, you can keep this section as a shorter reference. It formalizes the OOPs Designing Principles.
These principles can be remembered as EDAM (Entities Description Attributes Methods)
Consider a shopping cart an in e-commerce application.
Principle Entities: What are the entities involved?
- Shopping Cart
- Shop (the seller)
- ShoppedItems
Principle Describe: Describe these entities in a consistent manner
- Shopping cart has an owner user
- Shopping cart contains the items
- ShoppedItems have their item id, price, the shop from which this item is being bought
- We checkout the shopping cart
- Discount (assuming discount on overall shopping cart only)
Principle Attributes: What are the attributes of the Entities involved
- ShoppingCart
- shoppingCartId
- ownerUserId
- listOfItems
- totalDiscount
- ShoppedItem
- itemId
- price
- shop (type Shop)
- Shop
- userId
- starRating
- phoneNumber
- dateOfEnrollment
Principle Methods
- ShoppingCart – what can be done with the Shopping cart
- cancel()
- checkout()
- calculateDiscount()
- removeAllItems()
- clearItem(ShoppedItem)
- ShoppedItem
- none for our example
- Shop
- none for our example
Done with the first lesson 🙂
Now when doing actual class-designing, if ever in doubt, the coders can relate to the English language and these principles. During the design reviews, we have much less OOPs related design errors now – the approach is working well !
Any thoughts on how should Polymorphism be explained in a similar way? Cows, ShoppingCart – think over it !
Further reading
http://sepwww.stanford.edu/sep/jon/family/jos/oop/oop1.htm
http://research.ijcaonline.org/volume47/number21/pxc3880574.pdf
Amazing…
LikeLike
Very well written prince. enjoyed reading it.
LikeLiked by 1 person
Are there any more articles?
LikeLike
Hi Abhijit, will be following up with more articles on OOPs as well as other technologies. Follow the blog to get the updates. Thanks for visiting !
LikeLiked by 1 person