ပရိုဂရမ္မာ အေတာ္မ်ား သိျပီးသားျဖစ္မွာပါ။ ဒါေပမယ့္ မမွတ္မိေတာ့တို႕ ၊ သတိမရေတာ့တာတို႕ ေတြအတြက္ က်ေနာ္ျပန္ ေဖာ္ျပေပး လိုက္ပါတယ္။
အထူးသျဖင့္ အင္တာဗ်ဴးသြားမည့္ သူမ်ားအတြက္ အသံုး၀င္မယ္လို႕ ထင္ပါတယ္။
Polymorphism is often considered the most powerful feature of object-oriented programming. Greek for “many forms,” polymorphism is the ability to hide alternative implementations behind a common interface. This concept leverages inheritance and encapsulation among other OO concepts.
Polymorphism is the ability for objects of different types to respond to messages of the same type. The concept behind polymorphism is that a function or data type can be written in a generic way, so that it can handle any interactions to it regardless of the acting object’s type.
Using the abstract interfaces of objects, polymorphism can be used to create extensible and loosely-coupled programs. The benefit of this is that if new types are added, and they adhere to the common interface specified, then their impact on changing the system will be minimal.
When using inheritance based polymorphism, a class can be used as more than one type (MS Polymorphism, 2006). It can be used as its own type, any base types, or any interface type that implements its interface. In C#, every type is polymorphic. Types can be used as their own type, or as an object instance, since object is the base class of all types (MS Polymorphism, 2006).
The following scenario helps explain polymorphism. Let us assume two classes for now, class A and class B. Class A is our base class. With inheritance we know that any class that inherits from class A will inherit all of class A’s methods, fields, properties, and events. In the example below, when class B derives from A, it can choose to override the base class’s functionality.
Example 1
public class A
{
public virtual void DoSomething() {}
public virtual int SomeValue { Get { return 0; } }
}
public class B : A
{
public override void DoSomething() {}
public override int SomeValue { get { return 0; } }
}
B b = new B();
b.DoSomething(); // calls the override method in class B
Now, let’s create an instance of class A, casting our class B instance to it.
A a = (A)b; // create an instance of A casting our instance of B
a.DoSomething(); // calls the override method in class B
In Example 1, an instance of class A is created using the instance of object B. If this is confusing, then think of it as if class A were created using “A a = new B();” The object instance of class A is now using an object of the derived class B that has been cast to the base class type A. What does this mean? Well, think of it as though Class B is now being represented by a more generic object, class A.
Example 2
For another example, consider the following scenario. Human beings, whales, and dogs are related in that they are all part of the mammal class, or Mammalia. Mammals are grouped into another classification, phylum Chordata, or animals with vertebrae, or Vertebrata. I am using this example because animals of many differing species are all related in some sense, so they share similar characteristics. In the following examples, we will use less science and more OO concepts.
The Vertebrate class represents all objects that have a skull and a vertebra. This group includes mammals as well as non-mammals. These objects are able to show their skull and return a total vertebrae count. A spinal column is comprised of individual units, or vertebra.
The Mammal class represents all objects that can grow hair, have mammary glands, and without getting too scientific, have a higher rate of metabolism. For our example, all Mammal objects are able to grow hair and return their total number of mammary glands.
class Vertebrate
{
public virtual void ShowSkull() {}
public virtual int GetVertebraeCount( ) {}
}
class Mammal : Vertebrate
{
public virtual void GrowHair() {}
public virtual int GetMammaryGlandCount( ) {}
}
Canines are a type of Mammal. Before we can jump into our Beagle example, we need to see that a Beagle is a type of Canine, but it also inherits from more specific types of Canines, where each derived class offers something more specialized then its base class.
class Canine : Mammal {}
class Wolf : Canine {}
class DomesticDog : Wolf {}
class Beagle : DomesticDog {}
Human and Whale objects do not derive from Canine, but they do derive from Mammal, so they will share similar traits with all mammals.
class Human : Mammal {}
class Whale : Mammal {}
To emphasize our point of polymorphism, we have the following code. Beagles, humans, and whales are all able to grow hair.
Beagle beagle = new Beagle();
beagle.GrowHair();
Human human = new Human();
human.GrowHair();
Whale whale = new Whale();
whale.GrowHair();
In a more abstract, or generalized way, we can also say.
Mammal b = new Beagle();
b.GrowHair();
Mammal h = new Human();
h.GrowHair();
Mammal w = new Whale();
w.GrowHair();
When we create a new Mammal object, giving it the type of Beagle, we are using polymorphism. Any time we are using a base class, we could be actually using an object of the base class type, or any object that derives from the base class. The Beagle class derives from the DomesticDog, which in turn derives from the Wolf, which in turn derives from the Canine, which in turn derives from Mammal. We are four generations deep in our inheritance hierarchy, but we are still able to represent a Beagle object using the Mammal class.
At the same time, humans and whales may not seem remotely related, but they are, since they both inherit from class Mammal. We are able to represent these objects as well, using polymorphism, as seen with the following.
Mammal whale = new Whale();
whale.GrowHair();
Mammal human = new Human();
human.GrowHair();
If we wanted to go a step further, we could include sharks in our example, but we would need to use the Vertebrate class, since sharks are not derived from Mammals. We lose more specific functionality when moving up the hierarchy chain. For example, when casting a Human object to a Vertebrate object, we can no longer request human.GrowHair(); This gives us something to think about when designing systems.
Vertebrate shark = new Shark();
shark.GetVertebraeCount();
Vertebrate human = new Human();
human.GetVertebraeCount();
More on Polymorphism
As messages are sent to objects, each object must have a predefined method to respond to that message. In an inheritance hierarchy, each derived class inherits its interface from its base class. Since each derived class is a separate entity, each may require a separate response to the same message (Weisfeld, 2000).
For example, when a message is sent to GetVertebraeCount, the first thing we ask is, get vertebrae count of what? We cannot get a vertebrae count because it is too abstract, so we must provide an implementation of a concrete Vertebrate, such as Shark or Human. While Vertebrate has a GetVertebraeCount method, we need to use the more specific overridden methods found in the derived classes. We can treat Human, Shark, and Snake as Vertebrate objects, and send a GetVertebraeCount message. The end result of these messages will be different since each provides a specific implementation. Each class is able to respond in its own unique way to the same GetVertebraeCount message. This is polymorphism.
Polymorphism in Design
Polymorphism solves an important piece of the puzzle when it comes to designing a system. Good design principles tell us to program to an interface, not to an implementation. When using polymorphism, we are able to adhere to this concept, and abstract out implementations in such a way our system’s interface will not change when implementation requirements do. Once our system depends on interfaces only, we are decoupled from the implementation. The implementations can vary while our interfaces remain the same. This promotes flexibility.
References:
MS Polymorphism. (n.d.). Retrieve May 29, 2006, from http://msdn2.microsoft.com/en-us/library/ms173152(VS.80).aspx