Inheritance
## Learning Objectives
- Understand inheritance
- Master polymorphism
- Work with abstract classes
- Implement interfaces
## What is Inheritance?
### "Is-a" Relationship
```csharp
// Base class
class Animal
{
public string Name { get; set; }
public void Eat()
{
Console.WriteLine("Eating");
}
}
// Derived class
class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Woof!");
}
}
// Usage
Dog dog = new Dog();
dog.Name = "Buddy";
dog.Eat(); // From base class
dog.Bark(); // From Dog class
```
## protected Access
### Accessible in Derived Classes
```csharp
class Animal
{
protected string _name; // Accessible to derived classes
private int _age; // Not accessible outside class
}
class Dog : Animal
{
public void Introduce()
{
_name = "Buddy"; // OK - _name is protected
// _age = 5; // Error - _age is private
}
}
```
## Base Class Reference
### Polymorphism
```csharp
class Animal
{
public string Name { get; set; }
public virtual void MakeSound()
{
Console.WriteLine("Some sound");
}
}
class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Woof!");
}
}
class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow!");
}
}
// Usage
Animal[] animals = { new Dog(), new Cat(), new Animal() };
foreach (Animal animal in animals)
{
animal.MakeSound(); // Calls appropriate override
}
// Output: Woof! Meow! Some sound
```
## virtual and override
### Virtual Methods
```csharp
class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("...");
}
}
```
### Override Methods
```csharp
class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Woof!");
}
}
```
### sealed (Prevent Override)
```csharp
class Dog : Animal
{
public sealed override void MakeSound()
{
Console.WriteLine("Woof!");
}
}
class Husky : Dog
{
// Cannot override MakeSound - it's sealed
}
```
## Abstract Classes
### Cannot Be Instantiated
```csharp
abstract class Shape
{
public abstract double Area(); // Must be implemented
public abstract double Perimeter();
public void Print()
{
Console.WriteLine($"Area: {Area()}");
}
}
class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public override double Area() => Width * Height;
public override double Perimeter() => 2 * (Width + Height);
}
// Shape s = new Shape(); // Error - cannot instantiate
Shape r = new Rectangle { Width = 5, Height = 3 };
```
### abstract vs virtual
| abstract | virtual |
|----------|---------|
| Must override | Can optionally override |
| No body | Has body |
| Cannot instantiate | Can instantiate |
## Interfaces
### Contract Definition
```csharp
interface IShape
{
double Area();
double Perimeter();
}
interface IPrintable
{
void Print();
}
class Rectangle : IShape, IPrintable
{
public double Width { get; set; }
public double Height { get; set; }
public double Area() => Width * Height;
public double Perimeter() => 2 * (Width + Height);
public void Print()
{
Console.WriteLine($"Rectangle: {Width} x {Height}");
}
}
```
### Interface Naming Convention
- Start with "I" (e.g., IDisposable, IEnumerable)
- Describe capability (IComparable, ICloneable)
### Interface vs Abstract Class
| Interface | Abstract Class |
|-----------|----------------|
| No implementation | Can have implementation |
| Multiple allowed | Single only |
| No state | Can have state |
| Public by default | Can have access modifiers |
## Default Interface Implementation (C# 8+)
```csharp
interface IAnimal
{
void Speak();
public void PrintSpecies()
{
Console.WriteLine("Generic animal");
}
}
class Dog : IAnimal
{
public void Speak()
{
Console.WriteLine("Woof!");
}
}
Dog dog = new Dog();
dog.Speak();
((IAnimal)dog).PrintSpecies(); // Must cast
```
## Polymorphism Example
### Shape Hierarchy
```csharp
interface IShape
{
double Area();
}
class Circle : IShape
{
public double Radius { get; set; }
public double Area() => Math.PI * Radius * Radius;
}
class Rectangle : IShape
{
public double Width { get; set; }
public double Height { get; set; }
public double Area() => Width * Height;
}
// Calculate total area
IShape[] shapes = { new Circle(5), new Rectangle(4, 6) };
double totalArea = 0;
foreach (IShape shape in shapes)
{
totalArea += shape.Area();
}
```
## base Keyword
### Access Base Class Members
```csharp
class Animal
{
public string Name { get; set; }
public virtual void Speak()
{
Console.WriteLine("...");
}
}
class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
public void SpeakWithName()
{
base.Speak(); // Calls Animal.Speak()
Console.WriteLine($"My name is {Name}");
}
}
```
### base in Constructors
```csharp
class Animal
{
public string Name { get; set; }
public Animal(string name)
{
Name = name;
}
}
class Dog : Animal
{
public string Breed { get; set; }
public Dog(string name, string breed) : base(name)
{
Breed = breed;
}
}
```
## Casting and typeof
### Explicit Casting
```csharp
Animal animal = new Dog();
Dog dog = (Dog)animal; // Explicit cast
// Safe cast with 'as'
Dog? dog2 = animal as Dog;
if (dog2 != null)
{
dog2.Bark();
}
```
### is Operator with Pattern
```csharp
Animal animal = new Dog();
if (animal is Dog dog) // Pattern matching
{
dog.Bark(); // dog is in scope
}
// Or
if (animal is Dog)
{
Dog dog = (Dog)animal;
dog.Bark();
}
```
## Object Class
### All Classes Derive from object
```csharp
class Person
{
public string Name { get; set; }
}
// These are equivalent:
Person p = new Person();
object o = new Person();
```
### Methods from object
```csharp
object o = new Person { Name = "Alice" };
o.ToString(); // "Person" or overridden
o.GetHashCode();
o.Equals(other);
o.GetType();
```
## Summary
- Inheritance: class derives from another class
- protected: accessible in derived classes
- virtual/override: for polymorphism
- abstract: must override, cannot instantiate
- interface: contract, multiple allowed
- base: access base class members
- is/as: type checking and casting
- All types derive from object
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →