Inheritance and Polymorphism in C#: Virtual Methods, Abstract Classes, Interfaces & Best Practices
1. Inheritance and Polymorphism
Q: What is inheritance in C#?
Inheritance is an OOP principle where a derived (child) class inherits members (fields, properties, methods) from a base (parent) class, promoting code reuse and hierarchical relationships. In C#, a class can inherit from one base class using the : operator.
Syntax:
class BaseClass { /* Members */ }
class DerivedClass : BaseClass { /* Additional members */ }
Q: What is polymorphism in C#?
Polymorphism allows objects of different classes to be treated as objects of a common base class, enabling flexible and extensible code. C# supports:
- Compile-time Polymorphism: Achieved via method overloading (covered previously).
- Runtime Polymorphism: Achieved via method overriding and interfaces, using
virtualandoverridekeywords.
Q: How do inheritance and polymorphism differ from C/C++?
- C#: Single inheritance only, managed, type-safe, supports interfaces for multiple inheritance-like behavior. Uses
virtual/overridefor polymorphism. - C++: Supports multiple inheritance, unmanaged, allows pointer-based polymorphism, more complex memory management.
- C: Lacks inheritance and polymorphism, uses structs without OOP.
- C# Advantage: Safer, simpler with single inheritance and interfaces, managed memory.
2. Types of Inheritance
Q: What are the types of inheritance supported in C#?
C# supports only single inheritance for classes (a class inherits from one base class). Multiple inheritance is not supported for classes but can be emulated using interfaces. Types of inheritance include:
- Single Inheritance: A derived class inherits from one base class.
- Multilevel Inheritance: A class inherits from a derived class, forming a chain (e.g., A → B → C).
- Hierarchical Inheritance: Multiple classes inherit from one base class (e.g., A → B, A → C).
- Multiple Inheritance (via Interfaces): A class implements multiple interfaces to inherit behavior.
Note: C# does not support multiple class inheritance (unlike C++).
Q: Can you give an example of single and multilevel inheritance in C#?
using System;
namespace InheritanceTypes
{
// Base class
class Animal
{
public string Name { get; set; }
public void Eat()
{
Console.WriteLine($"{Name} is eating.");
}
}
// Single inheritance: Dog inherits from Animal
class Dog : Animal
{
public void Bark()
{
Console.WriteLine($"{Name} is barking.");
}
}
// Multilevel inheritance: Puppy inherits from Dog
class Puppy : Dog
{
public void Play()
{
Console.WriteLine($"{Name} is playing.");
}
}
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog { Name = "Rex" };
dog.Eat(); // From Animal
dog.Bark(); // From Dog
Puppy puppy = new Puppy { Name = "Max" };
puppy.Eat(); // From Animal
puppy.Bark(); // From Dog
puppy.Play(); // From Puppy
}
}
}
Output:
Rex is eating.
Rex is barking.
Max is eating.
Max is barking.
Max is playing.
3. Method Overriding and Virtual Methods
Q: What is method overriding in C#?
Method overriding allows a derived class to provide a specific implementation of a method defined in a base class. The base class method must be marked virtual or abstract, and the derived class uses the override keyword. This enables runtime polymorphism.
Q: What are virtual methods in C#?
Virtual methods are methods in a base class marked with the virtual keyword, allowing derived classes to override them. They provide a default implementation that can be changed by derived classes.
Syntax:
class BaseClass {
public virtual void Method() { /* Default implementation */ }
}
class DerivedClass : BaseClass {
public override void Method() { /* New implementation */ }
}
Q: What is the difference between virtual and abstract methods?
- Virtual: Provides a default implementation that derived classes can override.
- Abstract: Declared without implementation, must be overridden in non-abstract derived classes (requires an abstract class).
Q: Can you give an example of method overriding and virtual methods in C#?
using System;
namespace MethodOverriding
{
class Vehicle
{
public virtual void Start()
{
Console.WriteLine("Vehicle starting...");
}
}
class Car : Vehicle
{
public override void Start()
{
Console.WriteLine("Car engine roaring!");
}
}
class ElectricCar : Vehicle
{
public override void Start()
{
Console.WriteLine("Electric car humming silently!");
}
}
class Program
{
static void Main(string[] args)
{
Vehicle vehicle = new Vehicle();
Vehicle car = new Car();
Vehicle electricCar = new ElectricCar();
vehicle.Start(); // Vehicle's implementation
car.Start(); // Car's overridden implementation
electricCar.Start(); // ElectricCar's overridden implementation
}
}
}
Output:
Vehicle starting...
Car engine roaring!
Electric car humming silently!
4. Abstract Classes and Interfaces
Q: What is an abstract class in C#?
An abstract class is a class marked with the abstract keyword that cannot be instantiated directly. It may contain abstract methods (no implementation, must be overridden) and non-abstract members. It's used as a base for derived classes.
Syntax:
abstract class BaseClass {
public abstract void AbstractMethod();
public void ConcreteMethod() { /* Implementation */ }
}
Q: What is an interface in C#?
An interface defines a contract of methods, properties, or events that implementing classes must provide. It's marked with the interface keyword and contains no implementation. Interfaces enable multiple inheritance-like behavior in C#.
Syntax:
interface IInterface {
void Method();
}
Q: What are the differences between abstract classes and interfaces?
- Abstract Class: Can have implementation, fields, and constructors; supports single inheritance; can have access modifiers.
- Interface: No implementation (until C# 8.0 default methods), no fields, no constructors; supports multiple inheritance; all members implicitly public.
- Use Case: Use abstract classes for shared code; use interfaces for flexible, contract-based design.
Q: Can you give an example of abstract classes and interfaces in C#?
using System;
namespace AbstractAndInterface
{
// Interface
interface IDrivable
{
void Drive();
}
// Abstract class
abstract class Vehicle
{
public string Model { get; set; }
public abstract void Start(); // Abstract method
public void Stop()
{
Console.WriteLine($"{Model} stopped.");
}
}
// Derived class implementing interface and inheriting abstract class
class Car : Vehicle, IDrivable
{
public Car(string model)
{
Model = model;
}
public override void Start()
{
Console.WriteLine($"{Model} starting with a roar!");
}
public void Drive()
{
Console.WriteLine($"{Model} driving smoothly.");
}
}
class Program
{
static void Main(string[] args)
{
Car car = new Car("Toyota");
car.Start(); // From Vehicle (abstract)
car.Drive(); // From IDrivable
car.Stop(); // From Vehicle
}
}
}
Output:
Toyota starting with a roar!
Toyota driving smoothly.
Toyota stopped.
Q: How do abstract classes and interfaces differ from C/C++?
- C#: Abstract classes are single-inheritance, interfaces support multiple inheritance. Managed, no pointers. Default interface methods (C# 8.0+).
- C++: Supports multiple class inheritance, abstract classes via pure virtual functions (
= 0), no interfaces (emulated with abstract classes). Uses pointers. - C: No abstract classes or interfaces, only structs.
- C# Advantage: Safer, simpler with interfaces, and modern features like default interface methods.
Q: What are common mistakes with inheritance and polymorphism in C#?
Inheritance:
- Overusing inheritance instead of composition or interfaces.
- Forgetting to mark base class methods as
virtualorabstractfor overriding.
Polymorphism:
- Incorrectly overriding methods without
overridekeyword. - Casting objects unsafely, causing runtime errors.
Abstract Classes/Interfaces:
- Instantiating abstract classes (not allowed).
- Forgetting to implement all interface members.
- Overcomplicating designs with deep inheritance hierarchies.
Q: What are best practices for inheritance, polymorphism, abstract classes, and interfaces in C#?
Inheritance:
- Prefer shallow hierarchies to avoid complexity.
- Use inheritance for "is-a" relationships (e.g.,
Caris aVehicle). - Seal classes (
sealed) to prevent unintended inheritance.
Polymorphism:
- Use
virtual/overridefor methods needing runtime polymorphism. - Test overridden methods to ensure correct behavior.
- Use
asor pattern matching (is) for safe type casting.
Abstract Classes:
- Use for shared implementation across derived classes.
- Mark methods as
abstractonly when no default implementation exists. - Avoid instantiable members in abstract classes.
Interfaces:
- Use for flexible, contract-based designs (e.g.,
IDrivable). - Keep interfaces focused and minimal.
- Leverage default interface methods (C# 8.0+) for optional behavior.
General:
- Favor composition over inheritance for flexibility.
- Use modern C# features (e.g., pattern matching in
switchoris). - Document inheritance hierarchies and interfaces with XML comments.