What an abstract class is
Sometimes a base class describes a family of types without being a complete thing itself. Every Animal can speak, but "an animal" in general makes no particular sound. An abstract class is a class you can't create objects from. It is a half-finished template that concrete subclasses complete.
Two rules
- You can't instantiate it.
new Animal()is a compile error (CS0144: cannot create an instance of the abstract type). You have to create a concrete subclass instead. - Subclasses must finish it. An abstract class may declare abstract methods: methods with a signature but no body. Every non-abstract subclass has to implement all of them, or the compiler rejects the class. The abstract class is a contract that the compiler enforces.
The syntax
abstract class Animal {
public abstract void Speak(); // no body, ends with a semicolon
}
class Dog : Animal {
public override void Speak() {
Console.WriteLine("Woof");
}
}
The keyword abstract appears on the class and on each abstract method. The subclass implements the method with override, exactly as with a virtual method. Two further rules apply to the override:
- The override must keep the same accessibility. An abstract method that is
publiccan't be overridden asprotectedorprivate. - The same name and parameters are required, or the method doesn't count as the implementation.
An abstract method can only appear inside an abstract class. Declaring one in a normal class is a compile error.
Mixing abstract and concrete members
An abstract class can also contain ordinary members: fields, constructors and methods with bodies. The subclasses inherit them as usual. Only the abstract methods have to be overridden.
abstract class Animal {
public string name;
public Animal(string name) {
this.name = name;
}
public abstract void Speak();
public void Introduce() {
Console.Write(name + ": ");
Speak();
}
}
class Dog : Animal {
public Dog() : base("Rex") { }
public override void Speak() {
Console.WriteLine("Woof");
}
}
Here Introduce is written once, in the abstract class, and calls Speak, which each subclass supplies. new Dog().Introduce() prints Rex: Woof. The abstract class has a constructor even though you can't call it with new: the subclass calls it with : base(...).
Abstract classes and polymorphism
You can't create an Animal, but you can still use the type for variables, parameters and arrays:
Animal a = new Dog();
a.Speak(); // Woof
The variable has the abstract type, and the object is a concrete subclass. The call runs the subclass's override, just as in the previous lesson.
Common mistakes
- Trying to instantiate the abstract class.
new Animal()never compiles. - Not implementing every abstract method. A class that derives from
Animalwithout overridingSpeakgets an error that it doesn't implement the inherited abstract member. Mark that classabstracttoo if you want to leave the work to its own subclasses. - Leaving out
override. A method namedSpeakwithout the keyword doesn't implement the abstract one. You get the same missing-member error, plus a warning that it hides the inherited method. - Changing the access level. An abstract
publicmethod must be overridden aspublic. - Giving an abstract method a body. Abstract methods end in a semicolon, with no braces. Use
virtualif you want a default implementation that subclasses may replace. - Using lowercase names. The lesson's method is
Speak, in PascalCase.
The exercise, step by step
The abstract Animal class is given. MainFunction creates a Dog named rex and calls Speak on it, but the Dog class doesn't exist yet. The expected output is:
Woof
- Declare the subclass below
Animal:class Dog : Animal. SinceAnimalcan't be instantiated, you need a concrete class forMainFunctionto create. - Implement the abstract method inside
Dog:public override void Speak(), with a body that writesWoofusingConsole.WriteLine. Theoverridekeyword is required, andpublicmatches the base declaration.
abstract class Animal {
public abstract void Speak();
}
class Dog : Animal {
public override void Speak() {
Console.WriteLine("Woof");
}
}
class Solution {
public void MainFunction() {
Dog rex = new Dog();
rex.Speak();
}
}
Key takeaways
- An abstract class can't be instantiated; it is meant to be inherited.
- Abstract methods have no body and must be overridden by every concrete subclass.
- Abstract classes can also hold fields, constructors and normal methods.
- Use
overridewith the same accessibility to implement an abstract method. - Variables of the abstract type can refer to concrete subclass objects, which gives you polymorphism.