Saturday, February 28, 2015

Good practice: Abstract class vs. Interface

Abstract class: Like a Noun! A group of similar things you can group together with one word. Can have implementation of methods and/or declared non-implemented methods. May or may not include abstract methods. However, if you have an abstract method, it does have to be inside of an abstract class (Got it? Just like rectangle is a square, but square is not a rectangle). A non-abstract class derived from an abstract class (abstract class itself cannot be instantiated) must include actual implementations of all inherited abstract methods and accessors.

Abstract Class Example
Interface: Like a Verb (Action)! Things that your class can do. The whole Interface must be implemented in the classes that implement it, you cannot pick an choose pieces you have to take the whole thing (all or nothing!)

Bare minimum blueprint instructions of what has to be inherited at a minimum. NO IMPLEMENTATION. You want a house? You need a floor, 4 walls, and a roof. You do have to implement every single thing mentioned in the interface. So don't put a chimney and fireplace in your interface if you live in Florida.

Interface Example:
Don't put in extra stuff that some things will need and other won't, put in things that you know every single thing would need. For a car to work.. you need tires, an engine, and brakes. Don't add an electric motor to your IDriveable, you don't have to have an electric motor. You can specify that later. You know you don't want to ever instantiate a "car" as no one really has just "generic car" they have their Ford Mustang, Tesla, Corvette, whatever.

You can inherit many interfaces! As many as you like! You can make many separate interfaces for different components and inherit what you need out of it. Let's say we have multiple interfaces.. one each for hands, feet, head, ears, fur, tail, scales, wings:

  • Lizard implements hands, feet, head, tail, scales
  • Cat implements hands, feet, head, ears, fur, tail
  • Bird implements feet, tail, and wings
  • Fire breathing dragon implements hands, feet, head, ears, tail, scales, wings
Summary: You use abstract classes and interfaces to add functionality, increase code re-useability/reduce repetitive code, and streamline functionality. Yes you could avoid using these completely, but your code would eventually get very repetitive and you will find yourself doing a lot of extra and unnecessary work. Don't put in extra stuff into either, just the bare minimum that has to fit into whatever inherit/implements the abstract class/interface. If you find yourself wanting to only take pieces of an abstract class or an interface, try breaking them up into difference classes/interfaces, there was probably a better way to design (plan ahead :) ?). Use an abstract class as a base when you are making many similar things that you can group together (i.e. mammals) and use interfaces (as many as you want!) for small functional parts.

Takeaway from examples: Based on my example.. Pokemon makes a great base class. Every type of Pokemon from Pikachu to Charizard will have HP and be able to Attack() and can Heal(). However, NOT every Pokemon is considered cute or a thunder type.. so these make great Interfaces. Some Pokemon are BOTH cute and thunder type like Pikachu and thus can inherit both interfaces. Pikachu can take the one base class Pokemon, plus both interfaces as seen below: