Introduction
Every time I read about a Technical Interview, one question is always out there. What is the difference between an Abstract Class and an Interface and why would you use one over the other? It seems like a simple question but most often, the answer to this question seems insufficient for the interviewer and can cost you a job. So, I decided to write a series of articles about them and have tried to explain it in as simple a manner as I can, keeping in mind the interviewer's perspective. Regarding the title of the series, my intention is not to portray these concepts as villains. These are the most important concepts in C# and without them we cannot achieve better code efficiency. This series is all about their role in a technical interview. If you haven't prepared them well, it can cost you a job. So, these concepts are not villains but their role in an interview surely is.
I always try to learn a new concept with the simple approach: "What, Why and How".
- What: What is it?
- Why: Why do I need to learn it?
- How: How can I work with it?
I used the same approach to write this article. I divided this article into two parts. In the first part, I'll focus on Abstract Classes and in my second article, I'll talk about Interfaces and the difference between the two.
Roadmap
Following is the road map of the series of articles under the title "Abstract Class & Interface: Two Villains of Every Interview":
Abstract Class
What is an Abstract Class?
The dictionary meaning of the word "abstract
" is a thought or idea that has no physical existence and is just conceptual. We can use the idea to build something of a physical existence. In the MSDN Library, the "abstract
" keyword indicates that the thing has a missing or incomplete implementation and must be completed by others.
The abstract
keyword can be used with classes, methods, properties, indexers and events. If we use the abstract
keyword with a class, it indicates that the class is intended to be a base class and can have abstract
methods (ideas) that must be implemented in a derived class (physical existence).
An abstract
class is a special kind of class that has no implementation. It cannot be instantiated. Its implementation logic is provided by the classes that derive from it. It can have both abstract
as well as non-abstract
methods.
It is not compulsory to have only abstract
methods in an abstract
class. We can also have an abstract
class with only non-abstract
methods.
Why do we need an Abstract Class?
With an Abstract
Class, we can provide some kind of default functionality for all derived classes to extend from. This is useful to avoid code duplication in many cases.
Suppose we are defining an iPhone
class for Apple and then inheriting it to iPhone5
and iPhone5s
subclasses. Practically, we don't want an object of an iPhone
class since we first need to know the model of iPhone
. So, the iPhone
class should be an abstract
class that contains some predefined functions like Call()
and SMS()
for all iPhone models to share . We can also add abstract
methods like Model()
and Color()
into the iPhone class that must be implemented by all the subclasses inheriting iPhone. The main advantage of this approach is, whenever we inherit the iPhone
class into a derived class, say iPhone5s
, we need not define the Call()
and SMS()
methods again. We just need to implement the abstract
methods and we are good to go. It helps to provide default functionality in all the derived classes and also avoids code duplication.
Abstract
classes are also useful in the case of modifications to the project. If you plan on updating the base class in your project, it is better to make the class abstract
. Because you can define a functionality in an abstract
base class and automatically all the inheriting classes will have the same functionality without disturbing the hierarchy.
How to define an Abstract Class?
As we have discussed earlier, classes can be declared as abstract
by putting the keyword abstract
before the class definition. So, let's get started with Abstract
Class by using a simple console application.
Create a console application project in Visual Studio and name it "AbstractClassDemo
".
By default, it gives a class named Program
with Main
method in it for code execution. We can create an abstract
class by putting the keyword abstract
before a class definition as follows:
using System;
namespace AbstractClassDemo
{
abstract class iPhone { }
class Program
{
static void Main(string[] args) { }
}
}
The code above defines a simple abstract
class. However, we cannot create an object/instance of abstract
class. It gives us an error straightaway.
using System;
namespace AbstractClassDemo
{
abstract class iPhone { }
class Program
{
static void Main(string[] args)
{
iPhone iphone = new iPhone();
}
}
}
So, we need to define members in it that can get inherited in derived classes. We can define abstract
as well as non-abstract
members in an abstract
class. An abstract
class with non-abstract
method is as follows:
using System;
namespace AbstractClassDemo
{
abstract class iPhone
{
public void Call()
{
Console.WriteLine("Call Method: This method provides Calling features");
}
}
class Program
{
static void Main(string[] args)
{
}
}
}
The iPhone
class shows a non-abstract
method Call()
that provides the default functionality to all sub classes that are derived from it. We cannot create an object of iPhone
class but we can still use the Call()
method in derived classes.
using System;
namespace AbstractClassDemo
{
abstract class iPhone
{
public void Call()
{
Console.WriteLine("Call Method: This method provides Calling features");
}
}
class Program: iPhone
{
static void Main(string[] args)
{
Console.Writeline("/////////////// - Abstract Class Demo - ///////////////");
Program program = new Program();
program.Call();
Console.ReadKey();
}
}
}
The code above shows a simple inheritance of an abstract
class into a concrete class. This type of inheritance can also be done by two concrete classes. So, why do we want an abstract
class?
The answer is, to provide default functionality and to add abstract
methods. The iPhone
class is inherited by all iPhone
models, so the Call()
method is required in all the models. It is better to define a Call()
method in the abstract
class so that each derived class can have the Call()
method automatically and doesn't need to define it again.
Each iPhone
model has some of its own features like Color
and Model
. So, we can define a contract in an abstract
class that must be implemented in derived classes as per their requirements. These types of contracts are called abstract
methods and in this example is Model()
. Abstract
methods only have a signature and no implementation. It is a kind of contract that forces all the subclasses to implement it.
Like the abstract
class, abstract
methods are also declared using the abstract
keyword. It may be noted that an abstract
method cannot be private
or it gives an error:
using System;
namespace AbstractClassDemo
{
abstract class iPhone
{
public void Call()
{
Console.WriteLine("Call Method: This method provides Calling features");
}
abstract void Model();
}
class Program
{
static void Main(string[] args)
{
}
}
}
If we compile this code, it gives us an error:
So, the correct way to declare an abstract
method is as follows:
using System;
namespace AbstractClassDemo
{
abstract class iPhone
{
public void Call()
{
Console.WriteLine("Call Method: This method provides Calling features");
}
public abstract void Model();
}
class Program
{
static void Main(string[] args)
{
}
}
}
The Model()
method enforces all the derived classes to implement it. We can define a new concrete class iPhone5s
that inherits the abstract
class iPhone
and provides the definition of Model()
method.
using System;
namespace AbstractClassDemo
{
abstract class iPhone
{
public void Call()
{
Console.WriteLine("Call Method: This method provides Calling features");
}
public abstract void Model();
}
class iPhone5s: iPhone
{
}
class Program
{
static void Main(string[] args)
{
}
}
}
If we don't provide the definition of the abstract
method in the derived class, it throws an error:
Ok. Let's provide the definition of Model()
method in the derived class:
using System;
namespace AbstractClassDemo
{
abstract class iPhone
{
public void Call()
{
Console.WriteLine("Call Method: This method provides Calling features");
}
public abstract void Model();
}
class iPhone5s: iPhone
{
public void Model()
{
Console.WriteLine("Model: The model of this iPhone is iPhone5s");
}
}
class Program
{
static void Main(string[] args)
{
}
}
}
Now we have defined the Model()
method in the class iPhone5s
. Let's compile the code above. Whoa, it gives us an error plus a warning.
The error says "The Model()
method is not implemented in derived class". It seems fair since we aren't overriding the base method, which means the compiler believes that there is no implementation of the Model()
method in the derived class.
It also gives us a warning "To make the current member override that implementation, add the override keyword, otherwise add the new
keyword". It means that the compiler is confused about the Model()
method we declared in the iPhone5s
class.
If you want to override the base class method in derived class, use the override
keyword with the method and if your derived class method is not related in any way with the base class method, use the new
keyword. The new
keyword signifies that the method in the derived class has nothing to do with the base class method.
In our case, we want the base class method to be defined in the derived class. So, we use the override
keyword. Also, we can add local methods in the iPhone5s
class:
using System;
namespace AbstractClassDemo
{
abstract class iPhone
{
public void Call()
{
Console.WriteLine("Call Method: This method provides Calling features");
}
public abstract void Model();
}
class iPhone5s: iPhone
{
public override void Model()
{
Console.WriteLine("Model: The model of this iPhone is iPhone5s");
}
public void LaunchDate()
{
Console.WriteLine("Launch Date: This iPhone was launched on 20-September-2013");
}
}
class Program
{
static void Main(string[] args)
{
}
}
}
All good. Let's use the iPhone5s
class that now has methods from the abstract
class as well as its own methods.
using System;
namespace AbstractClassDemo
{
abstract class iPhone
{
public void Call()
{
Console.WriteLine("Call Method: This method provides Calling features");
}
public abstract void Model();
}
class iPhone5s: iPhone
{
public override void Model()
{
Console.WriteLine("Model: The model of this iPhone is iPhone5s");
}
public void LaunchDate()
{
Console.WriteLine("Launch Date: This iPhone was launched on 20-September-2013");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("/////////////// - Abstract Class Demo - ///////////////");
Console.WriteLine("iPhone 5s:");
iPhone5s iphone5s = new iPhone5s();
iPhone5s.Call();
iPhone5s.Model();
iPhone5s.LaunchDate();
Console.ReadKey();
}
}
}
If we run the code, it works perfectly.
In the preceding example, I explained how to use an abstract
class in a very simple way. We are able to implement an abstract
class and its abstract
members into a concrete class. The following are some key points to be remembered when working with abstract
classes.
Key Points
- We cannot create an object of
Abstract
class, but we can create a reference of it.
using System;
namespace AbstractClassDemo
{
abstract class absClass{ }
class Program
{
static void Main(string[] args)
{
absClass cls;
}
}
}
- An inheritance between
abstract
to abstract
classes is possible. We don't need to implement abstract
methods of the base abstract
class into a derived abstract
class. We can implement it later in concrete classes.
using System;
namespace AbstractClassDemo
{
abstract class absClassA
{
public abstract void SomeMethod();
}
abstract class absClassB: absClassA {
}
class Program: absClassB
{
public override void SomeMethod()
{
}
public static void Main(string[] args)
{
}
}
}
- An
abstract
class can never be sealed
or static
. If we compile the below code, it throws an error.
using System;
namespace AbstractClassDemo
{
sealed abstract class absClassA
{
}
class Program
{
public static void Main(string[] args)
{
}
}
}
- An
abstract
class can have abstract
as well as non abstract
methods.
- The
abstract
keyword can be used with class, methods, properties, indexers and events.
Abstract
members can only be declared inside an abstract
class.
- An
abstract
member cannot be static
or private
.
- An
abstract
method cannot be marked virtual
.
- A concrete class cannot inherit more than one
abstract
class, in other words multiple inheritance is not possible.
- Without an
abstract
class, we cannot implement the Template Method Pattern.
Conclusion
I hope this article helps you to understand the various possibilities of Abstract
Classes. In Part 2
of my article, I'll talk about Interfaces
. Your feedback and constructive criticism is always appreciated, keep it coming. Until then, try to put a ding in the universe!