CSC/ECE 517 Fall 2009/wiki2 4 dn

From Expertiza_Wiki
Jump to navigation Jump to search

A large fraction of the if-statements in o-o programs could be replaced by uses of polymorphism, which would lead to more modular and maintainable programs. Explain why if-statements are error prone if there is any chance that future development may require them to change. Give examples of if-statements that can be replaced by elegant uses of polymorphism, trying to find some useful replacements that are not obvious. Concentrate on polymorphism, not other reasons for avoiding use of ifs.


The If Statement

The if-then statement is the most basic of all the control flow statements. It tells a program to execute a certain section of code only if a particular test evaluates to true.

if (daytime is morning)
{
  print "good morning"
}
else if (daytime is afternoon)
{
  print "good afternoon"
}
....
....

When and why are if-statements error prone?

Maintainability and Extensibility

Methods that use conditional if-statements can be hard to maintain and extend.

Public class  operator
{
   public int calculate(int a, int b)
   {
      if (operator = "+")
      {
         result = a+b
      }
      else if(operator = "-")
      {
         result = a-b
      }
    }
}

In the above example, if the programmer wanted to extend her code to handle multiplication, division and the mod operation; she would have to write an explicit conditional statement to handle each of these. If the condition is checked in multiple places then the programmer will have to add the additional conditional statement in each of these places. This not only results in duplication of code but is also highly error prone.

Testing

Sometimes in a program the same condition may have to be checked in multiple places.

Class ReadWrite
{
  read()
  {
    if(flag is enabled)
    {
      read a
    }
    else if(flag is not enabled)
    {
      read b
    }
  }
  write() 
  {
    if(flag is enabled)
    {
      write a 
    }
    else if(flag is not enabled)
    {
      write b
    }
  }
}

In the above example, flag is checked multiple times. The program needs to read a and write a or read b and write b. The program should not read a and write b or read b and write a. Since, the behavior that needs to be executed when the flag is enabled and when the flag is disabled is spread out testing this can be very difficult. If the condition needs to be checked more than twice then testing and debugging becomes even more complicated.

If statements and Polymorphism

Most if-statements such as the ones shown above can be replaced with polymorphism.

In object-oriented programming, polymorphism refers to a programming language's ability to process objects differently depending on their data type or class. More specifically, it is the ability to redefine methods for derived classes.Ref

Why should if-statements be replaced with polymorphism?

The essence of polymorphism is that it allows a programmer to avoid writing an explicit conditional for an object whose behavior varies depending on its type. Therefore object oriented programs have very few if-statements that switch on type strings.

Polymorphism allows a programmer to add new types very easily. This is particularly useful when the same set of conditions appear in many places in a program. The programmer has to find and update all the conditionals with the new type. But, with polymorphism you can just add a new sub class and provide the appropriate methods. Clients of the class don't need to know about the subclasses. This decreases dependencies in your application and makes updating easier.

When should if-statements be replaced with polymorphism?

All if-statements cannot be replaced with polymorphism. If-statements must be used when basic comparisons such as <,>,==, != are done.

Polymorphism should be used instead of conditionals-

  • If an object should behave differently based on its state.
  • If the same condition has to be checked in multiple places.

Examples of replacing if statements with polymorphism

Example 1: When behavior changes depending on the type of the object

The calculate function shown above which uses if statements to perform arithmetic operations can be re-written as follows using polymorphism:

public abstract class Operator
{    
   public abstract int calculate(int x, int y);
}
public class Add : Operator
{    
   public int calculate(int x, int y)
   {        
     return x + y;   
   }
}
public class Subtract : Operator
{
  public int calculate(int x,int y)
  {
    return x-y;
  }
}

Here, by making the calculate method abstract in the Operator class, we are enabling it to be overridden by the calculate methods in classes Add and Subtract. By doing this the functionality of each of the operator type is separated and therefore dependencies are minimized. Hence, a programmer can not only make updates easily but can also add new types of operators without actually accessing the source code.

Therefore, when you have a conditional that changes behavior depending on the type of an object, move each leg of the conditional to a subclass and make the original method abstract.Ref

Example 2: When the same set of conditionals is used in different places

Consider the example given above with class ReadWrite. The class has two methods read() and write() which reads a or b and writes a or b depending on whether flag is set or not.

The if statements can be replaced with polymorphism as follows to solve the testing problem mentioned above

public abstract class ReadWrite
{
  public abstract read();
  public abstract write();
}

class flagset : ReadWrite
{
  read()
  {
    read a
  }  
  write()
  {
    write a
  }
}

class flagnotset : ReadWrite
{
  read()
  {
    read b
  }  
  write()
  {
    write b
  }
}

Here, using subclasses, all the functionality that needs to be executed when the flag is set, is separated from the functionality that needs to be executed when the flag in not set. This makes testing and debugging easier and also makes the code more easily extensible.

Resources