(Basic) The rise of Polymorphismo
Bài đăng này đã không được cập nhật trong 3 năm
Background
In my first article ever, I've already mentioned about how these two approaches we know ("interface" and "abstract class") actually have their own special benefits (and their own hardcore fans as well). Let's take a look inside the abstract class first.
(Intermezzo) Clean and Clear vs Indirection
But before we get to it, please examine first these codes from our previous discussions :
public enum Attrib
{
Intelligence,
Strength,
Agility,
Will
}
public abstract class CHuman : CBeing
{
public abstract IDictionary<Attrib, int> Attribs { get; } //1st occurence
}
public abstract class CWearable : CMatter
{
public abstract BodyPart CorrespondingBodyPart { get; }
public abstract IDictionary<Attrib, int> AttributeModifiers { get; } //2nd occurence
}
Don't you know that we can make it any simpler by using a new derived class like this?
public class CAttribDictionary : Dictionary<Attrib, int>
{
}
So, we can change our previous codes to look like this :
public abstract class CHuman : CBeing
{
public abstract CAttribDictionary Attribs { get; } //simpler and more consistent
}
public abstract class CWearable : CMatter
{
public abstract BodyPart CorrespondingBodyPart { get; }
public abstract CAttribDictionary AttributeModifiers { get; } //simpler and more consistent
}
Do you feel it? How it makes our codes look simpler and more consistent? Because "Human" and "Wearable" classes sharing the same Attribute's data type, that's why.
Some may argue that this will only add another indirection, but everything has its cost, right? For me, why use object oriented methodology, if you cannot make it clean and clear, right?
Now is the time, when I introduce you to...
...Polymorphismo!
He's rising from the darkest universe, to meet his loyal followers : the clan of the class!
"Ok, cut the crap, will you." Hey, actually, with this power you can override any behaviours inherited from the parent class. Remember my article about inheritance? So, to show you clearly the real power of the class, let's change our legacy codes to this :
public enum BodyPart
{
Head,
Eye,
Ear,
Mouth,
Neck,
UpperBody,
Hands,
Finger,
Waist,
Legs,
Foot,
FullBody
}
//This class now has its own implementation for its original attributes
public abstract class CThing
{
//Add explicitly these two internal variables
protected int id;
protected string name;
//Change the 'abstract' keyword with 'virtual', and set all the getters
public virtual int Id
{
get { return id; }
}
public virtual string Name
{
get { return name; }
}
}
//Same here
public abstract class CMatter : CThing
{
protected int durability;
public virtual int Durability
{
get { return durability; }
}
}
//And here
public abstract class CWearable : CMatter
{
protected BodyPart correspondingBodyPart;
protected CAttribDictionary attributeModifiers;
public virtual BodyPart CorrespondingBodyPart
{
get { return correspondingBodyPart; }
}
public virtual CAttribDictionary AttributeModifiers
{
get { return attributeModifiers; }
}
}
//Now this derived class only need to deal with its own constructor, and nothing else
public class Hat : CWearable
{
public Hat(int id, string name, int durability)
{
this.id = id;
this.name = name;
this.durability = durability;
}
//Polymorpismo hits it here!
public override BodyPart CorrespondingBodyPart
{
get
{
return BodyPart.Head;
}
}
}
//And this class as well
public class Costume : CWearable
{
public Costume(int id, string name, int durability, CAttribDictionary attributeModifiers)
{
this.id = id;
this.name = name;
this.durability = durability;
this.attributeModifiers = attributeModifiers;
}
//Polymorpismo hits it again here!
public override BodyPart CorrespondingBodyPart
{
get
{
return BodyPart.FullBody;
}
}
}
That's it! Polymorphismo has hit it twice! And he can hit any part of the class that marked with the "virtual" keyword. Yes, that's right! Because the keyword means, "Hey this is the part where you can 'override' if you don't really like the implementation derived from the parent class".
How is that, huh? Inheritance is not the end of all, fellas. You can still alter your destiny, and create your own future, because it's not written in stones.
So let's make some tests :
[TestMethod]
public void AskTheSimpleFactoryForACowboyHatUsingClass()
{
//Let's ask the factory for a cowboy hat
var CowboyHat = WearableFactory.GiveMe(WearableType.Hat, 1, "CowboyHat", 5, null);
//and test wether it is really a cowboy hat we ask for
Assert.IsInstanceOfType(CowboyHat, typeof(Hat));
Assert.AreEqual(1, CowboyHat.Id);
Assert.AreEqual("CowboyHat", CowboyHat.Name);
Assert.AreEqual(BodyPart.Head, CowboyHat.CorrespondingBodyPart); //This part has its own behaviour
Assert.AreEqual(5, CowboyHat.Durability);
}
Can't you see that? You still have all the attributes from your parent, but you can also expect some attributes to behave differently by design. Cool, isn't it?
That's the real power of Polymorphismo, and we call it "Polymorphism"!
Anyway, you can read about that WearableFactory in my previous article, just in case you wanna know what it is.
So, what it's all about, again?
###The class has the power of Polymorphism, that is an ability to have different implementation of behaviours derived from the parent class. Your concern is only with the differences, and let the nature of inheritance handles the rest.
What's next?
When classes have polymorphism, what about the interface? What it has to offer? Please follow me to know even further, why this approach has so many followers around the world.
All rights reserved