Abstract classes, marked by the keyword abstract in the class definition, are typically used to define a base class in the hierarchy. What's special about them, is that you can't create an instance of them - if you try, you will get a compile error. Instead, you have to subclass them, as taught in the chapter on inheritance, and create an instance of your subclass. So when do you need an abstract class? It really depends on what you do.
namespace AbstractClasses
{
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog();
Console.WriteLine(dog.Describe());
Console.ReadKey();
}
}
abstract class FourLeggedAnimal
{
public virtual string Describe()
{
return "Not much is known about this four legged animal!";
}
}
class Dog : FourLeggedAnimal
{
public override string Describe() { string result = base.Describe(); result += " In fact, it's a dog!"; return result; }} }
Abstract methods are only allowed within abstract classes. Their definition will look like a regular method, but they have no code inside them:
abstract class FourLeggedAnimal { public abstract string Describe(); }
So, why would you want to define an empty method that does nothing? Because an abstract method is an obligation to implent that very method in all subclasses. In fact, it's checked at compile time, to ensure that your subclasses has this method defined. Once again, this is a great way to create a base class for something, while still maintaining a certain amount of control of what the subclasses should be able to do. With this in mind, you can always treat a subclass as its baseclass, whenever you need to use methods defined as abstract methods on the baseclass. For instance, consider the following example:
As you can see, we create an ArrayList to contain our animals. We then instantiate a new dog and a new cat and add them to the list. They are instantiated as a Dog and a Cat respectively, but they are also of the type FourLeggedAnimal, and since the compiler knows that subclasses of that class contains the Describe() method, you are actually allowed to call that method, without knowing the exact type of animal. So by typecasting to the FourLeggedAnimal, which is what we do in the foreach loop, we get access to members of the subclasses. This can be very useful in lots of scenarios.
namespace AbstractClasses { class Program { static void Main(string[] args) { System.Collections.ArrayList animalList = new System.Collections.ArrayList(); animalList.Add(new Dog()); animalList.Add(new Cat()); foreach(FourLeggedAnimal animal in animalList) Console.WriteLine(animal.Describe()); Console.ReadKey(); } } abstract class FourLeggedAnimal { public abstract string Describe(); } class Dog : FourLeggedAnimal { public override string Describe() { return "I'm a dog!"; } } class Cat : FourLeggedAnimal { public override string Describe() { return "I'm a cat!"; } } }
As you can see, we create an ArrayList to contain our animals. We then instantiate a new dog and a new cat and add them to the list. They are instantiated as a Dog and a Cat respectively, but they are also of the type FourLeggedAnimal, and since the compiler knows that subclasses of that class contains the Describe() method, you are actually allowed to call that method, without knowing the exact type of animal. So by typecasting to the FourLeggedAnimal, which is what we do in the foreach loop, we get access to members of the subclasses. This can be very useful in lots of scenarios.