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 Define an Interface In the following code listing an interface named Iproduct has been defined. Listing 2 public interface Iproduct Implementation In the following code listing the Iproduct interface has been implemented by the class implementInterface. Listing 3 public class implementInterface: Iproduct In the following code listing the abstract Class named Product has been implemented by the class implementAbstract. Listing 4 public class implementAbstract: Product How to Test In the following code listing abstract class implementation is being tested. Listing 5 ImplementAbstract testAbstract=new implementAbstract(); In the following code listing the implementation of our interface is being tested. Listing 6 ImplementInterface testInterface=new implementInterface(); 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 In the following code listing the implementation of a sealed class has been tested. Listing 10 classSealed sc=new classSealed(); 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 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. |