# OOP. Polymorphism

This topic contains 0 replies, has 1 voice, and was last updated by  Васильев Владимир Сергеевич 6 months, 3 weeks ago.

• Author
Posts
• #4087

Of all the principles of object-oriented programming, this one is the most difficult to explain, but it’s also extremely useful. First, where does its name come from?

Polymorphism, in Greek, means the multiplicity of forms. In terms of programming, it is something capable to represent the same thing in different ways and, on the other hand, it allows to behave things which are not identical, in the same way.

If we are talking about data types, polymorphism makes it possible to use instances of different classes as representatives of the same class. You already want to know how?

Let’s take an example with class Transport. It implements the basic functionality of any vehicle – Move().

Its derived classes (Car, Airplane, Tram) override its method of locomotion in their own way. But wherever we use them, we can count on the presence of common functionality. Though, of course, we can not expect it to be similar in every derived class.

class Transport
{
public virtual void Move ()
{
// just implementing a moving ability
}
}
class Airplane: Transport
{
public override void Move ()
{
base.Move ();
// fly
}
}
class Car: Transport
{
public override void Move ()
{
// ride
}
}
class Tram: Transport
{
public override void Move ()
{
// suffer (who knows what the Ukrainian trams are, will understand :))
}
}

Let’s pay attention to the modifier virtual, tagging method Move () in the base class Transport. It means that we can override the implementation of this method in any successor, if it does not suit us in its original way. Also pay attention to the modifier override, tagging method Move () in child classes . Here it means that we are going to give their own implementation of the base class method. These two modifiers (virtual and override) are used in pairs. You can not override the parent type method, if it is not marked as virtual. But, on the other hand, we are not necessaryly required to override a virtual method of the base type.

Let’s test the use of all classes derived from the Transport class. We place references to all three classes into one collection, setting their base type as the type of collection (List<Transport>). Then we use foreach loop to go through each object of collection and call method Move() from each of them. Of course it was clear that every object in this collection must have the method Move(), because their base type includes it.

class Program
{
static void Main ()
{
List <Transport> transport = new List <Transport> ();
// Fill collection
foreach (var t in transport)
{
t.Move ();
}
}
}

A similar situation occurs when a particular method takes a reference to the class Transport as a parameter. In this case we will be able to pass a reference to any class derived from it, as an argument.

Let’s see an example: class Tester includes a single method TestTransportUse () with a single parameter of type Transport. We are creating an instance of the Car class at the entry point and passing it to the method.

Since the functionality to which we refer is already implemented, starting from the base class (Transport), everything goes fine. Thus we can use non – identical data types in a similar way.

class Tester
{
public static void TestTransportUse (Transport t)
{
t.Move ();
}
}
class Program
{
static void Main (string [] args)
{
Car car = new Car ();
Tester.TestTransportUse (car);
}
}

Method overloading is also considered a particular case of polymorphism. What ‘s the idea?

We define a set of similar-name methods in the same class, which only differ in type, number, sequence of parameters. And after that we use them as a single method which can accept different sets of arguments. So, we create variations of the same method, and the version is determined dynamically when calling it.

For example, we have a class that performs simple arithmetic calculations. One of them calculates a quotient from two parameters of double type. All would be fine if the return value was rounded. But the best would be if in some cases we could explicitly set the number of digits after the floating point , which of course means the precision

Therefore, we overload this method, so that it was possible to set the precision of result value through the parameters .

class Calculator
{
// other methods of calculations
// ...
public string Divide (double num1, double num2)
{
return (num1 / num2). ToString ();
}
public string Divide (double num1, double num2, int precision)
{
return Math.Round (num1 / num2, precision, MidpointRounding.AwayFromZero). ToString();
}
}

Analyzing the results, we see that now we have 2 versions of the same method, that differ only in the set of the parameters. Now let’s see how it works:

class Program
{
static void Main (string [] args)
{
Calculator calc = new Calculator ();
Console.WriteLine (calc.Divide (5,7));
Console.WriteLine (calc.Divide (5,7,2));
}
}

After creating an instance of Calculator class, we call both versions of the method Divide(), one by one. It looks like it is the same method, only the number of parameters is different.

Thus, the multiplicity of forms can be manifested in many ways. But special cases of polymorphism in programming are: