Use Polymorphism (OO) to Remove Condition Checks


Polymorphism is one important feature of Object Oriented (OO) concept. In the following example, we want to compute the total amount of fuel required for three types of transport: Car, Airplane and Boat. Noted that there is a tank for car but two tanks (left, right or front, rear) for airplane or boat.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Car : Vehicle
{
    public int AmountOfFuelNeededToFillTank()
    {
        return 1;
    }
}
 
public class Airplane : Vehicle
{
    public int AmountOfFuelNeededToFillLeftFuelTank()
    {
        return 2;
    }
    
    public int AmountOfFuelNeededToFillRightFuelTank()
    {
        return 3;
    }
}
 
public class Boat : Vehicle
{
    public int AmountOfFuelNeededToFillFrontFuelTank()
    {
        return 4;
    }
    
    public int AmountOfFuelNeededToFillRearFuelTank()
    {
        return 5;
    }
}
public class Car : Vehicle
{
	public int AmountOfFuelNeededToFillTank()
	{
		return 1;
	}
}

public class Airplane : Vehicle
{
	public int AmountOfFuelNeededToFillLeftFuelTank()
	{
		return 2;
	}
	
	public int AmountOfFuelNeededToFillRightFuelTank()
	{
		return 3;
	}
}

public class Boat : Vehicle
{
	public int AmountOfFuelNeededToFillFrontFuelTank()
	{
		return 4;
	}
	
	public int AmountOfFuelNeededToFillRearFuelTank()
	{
		return 5;
	}
}

If you have designed like this, it would be not convenient to sum up total amount of fuels:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class FuelingStation
{
    public int AddFuelToTruck(List <Vehicle> vehiclesOnRoute)
    {
        var amountOfFuelToLoadOnTruck = 0;
        foreach (var vehicle in vehiclesOnRoute)
        {
            if (vehicle is Car)
            {
                amountOfFuelToLoadOnTruck += ((Car) vehicle).AmountOfFuelNeededToFillTank();
            }
            else if (vehicle is Airplane)
            {
                amountOfFuelToLoadOnTruck +=((Airplane) vehicle).AmountOfFuelNeededToFillLeftFuelTank();
                amountOfFuelToLoadOnTruck +=((Airplane) vehicle).AmountOfFuelNeededToFillRightFuelTank();
            }
            else if (vehicle is Boat)
            {
                amountOfFuelToLoadOnTruck +=((Boat) vehicle).AmountOfFuelNeededToFillFrontFuelTank();
                amountOfFuelToLoadOnTruck +=((Boat) vehicle).AmountOfFuelNeededToFillRearFuelTank();
            }
        }
        return amountOfFuelToLoadOnTruck;
    }
}
public class FuelingStation
{
	public int AddFuelToTruck(List <Vehicle> vehiclesOnRoute)
	{
		var amountOfFuelToLoadOnTruck = 0;
		foreach (var vehicle in vehiclesOnRoute)
		{
			if (vehicle is Car)
			{
				amountOfFuelToLoadOnTruck += ((Car) vehicle).AmountOfFuelNeededToFillTank();
			}
			else if (vehicle is Airplane)
			{
				amountOfFuelToLoadOnTruck +=((Airplane) vehicle).AmountOfFuelNeededToFillLeftFuelTank();
				amountOfFuelToLoadOnTruck +=((Airplane) vehicle).AmountOfFuelNeededToFillRightFuelTank();
			}
			else if (vehicle is Boat)
			{
				amountOfFuelToLoadOnTruck +=((Boat) vehicle).AmountOfFuelNeededToFillFrontFuelTank();
				amountOfFuelToLoadOnTruck +=((Boat) vehicle).AmountOfFuelNeededToFillRearFuelTank();
			}
		}
		return amountOfFuelToLoadOnTruck;
	}
}

The problem of the above code is that if you add one more type of vehicle, you have to change the implementation of method AddFuelToTrunk, which should not care to know too much details e.g. airplane has left and right tank etc. The conditions checks inside foreach also slow down the performance.

To solve this problem, we can declare an interface:

1
2
3
4
public interface IFuelable
{
    int GetTotalAmountOfFuelNeededForVehicle();
}
public interface IFuelable
{
	int GetTotalAmountOfFuelNeededForVehicle();
}

And we need to extend the interface for three types of transport:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Car : Vehicle, IFuelable
{
    public int GetTotalAmountOfFuelNeededForVehicle()
    {
        return AmountOfFuelNeededToFillTank();
    }
}
 
public class Airplane : Vehicle, IFuelable
{
    public int GetTotalAmountOfFuelNeededForVehicle()
    {
        return AmountOfFuelNeededToFillLeftFuelTank() + AmountOfFuelNeededToFillRightFuelTank();
    }
}
 
public class Boat : Vehicle, IFuelable
{
    public int GetTotalAmountOfFuelNeededForVehicle()
    {
        return AmountOfFuelNeededToFillFrontFuelTank() + AmountOfFuelNeededToFillRearFuelTank();
    }
}
public class Car : Vehicle, IFuelable
{
	public int GetTotalAmountOfFuelNeededForVehicle()
	{
		return AmountOfFuelNeededToFillTank();
	}
}

public class Airplane : Vehicle, IFuelable
{
	public int GetTotalAmountOfFuelNeededForVehicle()
	{
		return AmountOfFuelNeededToFillLeftFuelTank() + AmountOfFuelNeededToFillRightFuelTank();
	}
}

public class Boat : Vehicle, IFuelable
{
	public int GetTotalAmountOfFuelNeededForVehicle()
	{
		return AmountOfFuelNeededToFillFrontFuelTank() + AmountOfFuelNeededToFillRearFuelTank();
	}
}

Now, after this, the method AddFuelToTruck does not need to know how many tanks, but just the total amount of fuel.

1
2
3
4
5
6
7
8
9
public int AddFuelToTruck(List <IFuelable> vehiclesOnRoute)
{
    var amountOfFuelToLoadOnTruck = 0;
    foreach (var vehicle in vehiclesOnRoute)
    {
        amountOfFuelToLoadOnTruck += vehicle.GetTotalAmountOfFuelNeededForVehicle();
    }
    return amountOfFuelToLoadOnTruck;
}
public int AddFuelToTruck(List <IFuelable> vehiclesOnRoute)
{
	var amountOfFuelToLoadOnTruck = 0;
	foreach (var vehicle in vehiclesOnRoute)
	{
		amountOfFuelToLoadOnTruck += vehicle.GetTotalAmountOfFuelNeededForVehicle();
	}
	return amountOfFuelToLoadOnTruck;
}

In .NET, you can also use LINQ to make it concise:

1
2
3
4
public int AddFuelToTruck(List <IFuelable> vehiclesOnRoute)
{
    return vehiclesOnRoute.Sum(vehicle => vehicle.GetTotalAmountOfFuelNeededForVehicle());
}
public int AddFuelToTruck(List <IFuelable> vehiclesOnRoute)
{
	return vehiclesOnRoute.Sum(vehicle => vehicle.GetTotalAmountOfFuelNeededForVehicle());
}

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
427 words
Last Post: ChromeCast Review
Next Post: How to Calculate Mortgage Monthly Payment using Excel (with Formula) ?

The Permanent URL is: Use Polymorphism (OO) to Remove Condition Checks

2 Comments

  1. lini

Leave a Reply