Inheritance

Inheritance is one of the fundamental concepts in object-oriented programming. Think of it like a family tree - children inherit traits from their parents, and in programming, classes can inherit properties and methods from other classes!

In Dart, inheritance allows you to create a new class based on an existing class. The existing class is called the parent class (or superclass), and the new class is called the child class (or subclass).

Why Use Inheritance?

Inheritance helps you:

  • Reuse code - No need to write the same code again and again
  • Create relationships between classes
  • Extend functionality of existing classes
  • Maintain cleaner code structure

Basic Inheritance Syntax

To create inheritance in Dart, we use the extends keyword:

class ParentClass {
  // Parent class properties and methods
}

class ChildClass extends ParentClass {
  // Child class can use parent's properties and methods
  // Plus add its own new features
}

Real-World Example

Let's create a simple example with animals:

// Parent class
class Animal {
  String name;
  int age;
  
  Animal(this.name, this.age);
  
  void eat() {
    print('$name is eating');
  }
  
  void sleep() {
    print('$name is sleeping');
  }
}

// Child class inheriting from Animal
class Dog extends Animal {
  String breed;
  
  // Constructor calling parent constructor
  Dog(String name, int age, this.breed) : super(name, age);
  
  // Dog's own method
  void bark() {
    print('$name is barking: Woof! Woof!');
  }
  
  // Dog can also use inherited methods like eat() and sleep()
}

Using the Inherited Class

void main() {
  Dog myDog = Dog('Buddy', 3, 'Golden Retriever');
  
  // Using inherited methods
  myDog.eat();    // Output: Buddy is eating
  myDog.sleep();  // Output: Buddy is sleeping
  
  // Using Dog's own method
  myDog.bark();   // Output: Buddy is barking: Woof! Woof!
  
  // Accessing inherited properties
  print('${myDog.name} is ${myDog.age} years old');
}

The super Keyword

The super keyword is used to:

  • Call the parent class constructor
  • Access parent class methods and properties
class Vehicle {
  String brand;
  int year;
  
  Vehicle(this.brand, this.year);
  
  void start() {
    print('$brand vehicle is starting...');
  }
}

class Car extends Vehicle {
  int doors;
  
  Car(String brand, int year, this.doors) : super(brand, year);
  
  @override
  void start() {
    super.start(); // Call parent's start method
    print('Car engine is now running!');
  }
}

Method Overriding

Child classes can override (replace) parent class methods to provide their own implementation:

class Bird extends Animal {
  Bird(String name, int age) : super(name, age);
  
  @override
  void eat() {
    print('$name is pecking at seeds');
  }
  
  void fly() {
    print('$name is flying high!');
  }
}

Key Points to Remember

ConceptDescription
extendsKeyword used to create inheritance
superRefers to the parent class
@overrideAnnotation to override parent methods
ConstructorChild must call parent constructor using super()

Inheritance Chain

You can have multiple levels of inheritance:

class LivingBeing {
  void breathe() {
    print('Breathing...');
  }
}

class Animal extends LivingBeing {
  void move() {
    print('Moving...');
  }
}

class Mammal extends Animal {
  void feedMilk() {
    print('Feeding milk to babies');
  }
}

class Dog extends Mammal {
  void bark() {
    print('Barking...');
  }
}

In this example, Dog inherits from Mammal, which inherits from Animal, which inherits from LivingBeing. So a Dog object can use methods from all these classes!

Inheritance is like building blocks - you start with a basic foundation and keep adding more specific features as you go down the inheritance chain. It's a powerful way to organize your code and avoid repetition! 🏗️