Tuesday, October 4, 2011

Abstract classes, Sealed Classes, and Interfaces

Introduction


Using sealed classes is a new concept added in C#. It is difficult to say when we should use an abstract class and when we should use an interface. In general defining an abstract class without any implementation means with abstract members has the same effect as defining an interface; however there are a lot more differences than similarities between an abstract class and an interface. In this article I am not only trying to describe the concept of abstract classes, interfaces, and sealed classes, but also describe in what situation we should use which and how. The sample code snippets have been written in C#.
What is an Abstract class?


An abstract class only allows other classes to inherit from it and cannot be instantiated. When we create an abstract class, it should have one or more completed methods but at least one or more uncompleted methods and these must be preceded by the key word abstract. If all the methods of an abstract class are uncompleted then it is the same as an interface, but there is a restriction that it cannot make a class inherit from it, which means it can not work as a base class.
What is an Interface?


An interface is defined by the key word interface. An interface has no implementation; it only has the definition of the methods without the body. When we create an interface, we are basically creating a set of methods without any implementation. A class implementing an interface must provide the implementation of the interface members. All the methods and properties defined in an interface are by default public and abstract.
Define an Abstract Class
In the following code listing an abstract class named Product has been defined.
Listing 1
public abstract class Product
{
  //fields
  protected string id;
  protected double price;
  //properties
  public abstract string ID
  {
    get;
    set;
  }
 
  public abstract double Price
  {
    get;
    set;
 
  }
  public abstract double CalculatePrice();
}
Define an Interface
In the following code listing an interface named Iproduct has been defined.
Listing 2
public interface Iproduct
{
  string ID
  {
    get;
    set;
 
  }
 
  double Price
  {
    get;
    set;
 
  }
  double CalculatePrice();
}
Implementation
In the following code listing the Iproduct interface has been implemented by the class implementInterface.
Listing 3
public class implementInterface: Iproduct
{
  protected string id;
  protected double price;
  public string ID
  {
    get
    {
      return id;
    }
    set
    {
      id = value;
    }
  }
  public double price
  {
    get
    {
      return price;
    }
    set
    {
      price = value;
    }
 
  }
  public double CalculatePrice()
  {
    return Price * 1.25;
  }
In the following code listing the abstract Class named Product has been implemented by the class implementAbstract.
Listing 4
public class implementAbstract: Product
{
  public override string ID
  {
    get
    {
      return id;
    }
    set
    {
      id = value;
    }
 
  }
  public override double Price
  {
    get
    {
      return price;
    }
    set
    {
      price = value;
    }
 
  }
  public override double CalculatePrice
  {
    return Price * 1.25;
  }
 
}
How to Test
In the following code listing abstract class implementation is being tested.
Listing 5
ImplementAbstract testAbstract=new implementAbstract();
testAbstract.ID=”A1”;
testAbstract.Price=1000.00;
double amt=testAbstract.CalculatePrice();
Response.Write(“Total Net Price of Product : “ +” “+testAbstract.ID +” “+ “is+” “+amt);
Response.Write(“<br>”);
In the following code listing the implementation of our interface is being tested.
Listing 6
ImplementInterface testInterface=new implementInterface();
testInterface.ID=”B1”;
testInterface.Price=900.00;
double Iamt= testInterface.CalculatePrice();
Response.Write(“Total Net Price of Product : “ +” “+testInterface.ID +” “+ “is+” “+Iamt);
Response.Write(“<br>”);
It should be noted that static members are not inherited under any circumstances. Hence we can not declare a static method in an interface because interfaces have no implementation. We can, however, declare a method as static in an abstract class, because abstract classes can have implementations of static methods. This has been described in the following code listing:
Listing 7
In an abstract class:
public static void test()
{
}
But we can not write the following in an interface.
Listing 8
static void test();
Abstract Class vs. Interface


·         An abstract class may contain complete or incomplete methods. Interfaces can contain only the signature of a method but no body. Thus an abstract class can implement methods but an interface can not implement methods.
·         An abstract class can contain fields, constructors, or destructors and implement properties. An interface can not contain fields, constructors, or destructors and it has only the property's signature but no implementation.
·         An abstract class cannot support multiple inheritance, but an interface can support multiple inheritance. Thus a class may inherit several interfaces but only one abstract class.
·         A class implementing an interface has to implement all the methods of the interface, but the same is not required in the case of an abstract Class.
·         Various access modifiers such as abstract, protected, internal, public, virtual, etc. are useful in abstract Classes but not in interfaces.
·         Abstract classes are faster than interfaces.
Sealed Class


Classes can be declared as sealed. This is accomplished by putting the sealed keyword before the keyword class in the class definition. For example:
Listing 9
public sealed class classSealed
{
  // Class members here.
  public string ID;
  public double Price;
}
In the following code listing the implementation of a sealed class has been tested.
Listing 10
classSealed sc=new classSealed();
sc.ID=”C1”;
sc.Price=500.00;
double Samt=sc. CalculatePrice();
Response.Write(“Total Net Price of Product : “ +” “+sc.ID +” “+ “is+” “+Samt);
Response.Write(“<br>”);
A sealed class cannot be used as a base class. For this reason, it cannot also be an abstract class. Sealed classes are primarily used to prevent derivation. Because they can never be used as a base class, some run-time optimizations can make calling sealed class members slightly faster. Sealing a class means one can not derive from it. Sealing a method means one can not override it. In C# structs are implicitly sealed; therefore, they cannot be inherited. If we try to inherit from a sealed class in another class we will get compile time error about Inconsistent accessibility (code is shown in following code listing).
Listing 11
public class TestClass : classSealed
{
}
In C# a method can not be declared as sealed. However when we override a method in a derived class, we can declare the overridden method as sealed as shown below. By declaring it as sealed, we can avoid further overriding of this method.
Listing 12
public class testClass
{
  public int x;
  public int y;
  public virtual void testMethod(){
 
  }
 
}
 
public class TestClass: testClass
{
  public override sealed void testMethod(){
 
  }
}
So Which One Should I Use?
Abstract classes can add more functionality without destroying the child classes that were using the old version. Abstract classes provide a simple and easy way to version our components. By updating the base class, all inheriting classes are automatically updated with the change. In an interface, creation of additional functions will have an effect on its child classes due to the necessary implementation of interface Methods in classes. Abstract classes should be used primarily for objects that are closely related, whereas interfaces are best suited for providing common functionality to unrelated classes. Say there are two classes, bird and airplane, and both of them have methods called fly. It would be ridiculous for an airplane to inherit from the bird class just because it has the fly() method. Rather, the fly() method should be defined as an interface and both bird and airplane should implement that interface. If we want to provide common, implemented functionality among all implementations of component, we should use an abstract class. Abstract classes allow us to partially implement classes, whereas interfaces contain no implementation for any members. So the selection of interface or abstract classes depends on the needs and design of our project. We can make an abstract class, interface, or combination of both depending on our needs.
The most likely situation in which we make a class or method sealed will be if the class or method is internal to the operation of the library, class, or other classes that we are writing. Because any attempt to override some of its functionality will cause problems. We can mark a class or method as sealed for commercial reasons, in order to prevent a third party from extending our classes. For example, in the .NET base class library string is a sealed class.
We should not use the sealed key word on a method unless that method is itself an override of another method in some base class. If we are defining a new method and we don’t want anyone else to override it, we should not declare it as virtual in the first place. If however, we have overridden a base class method, the sealed keyword provides a way of ensuring that the override supplied to a method is a “final” override that means no one else can override it again.
References


Conclusion


Well, this is my thought on interfaces and abstract classes, we want to have an abstract class when concrete classes will be sharing similar implementation details, like each employee has a name, that field can be stored in the abstract class, and also the property to access that information can be in the abstract class.  So when we have similar classes that will share code use an abstract class, however if we have classes that are nothing to do with one another but share some aspect that they do not share a common ancestor then use an interface.  Use sealed classes when the class should not have any derived classes.