DEV Community

Cover image for Dart Abstract Classes and Polymorphism in Dart - Part 6
Sadanand gadwal
Sadanand gadwal

Posted on • Updated on

Dart Abstract Classes and Polymorphism in Dart - Part 6

Understanding Abstract Classes and Runtime Polymorphism in Dart .

In Dart, abstract classes serve as blueprints for other classes, defining common behaviors and properties that subclasses can inherit and implement. This enables polymorphic behavior, allowing different objects to respond to the same message in different ways based on their types. Let's delve into the code examples provided to understand abstract classes and runtime polymorphism in Dart.

1) Abstract Classes
Abstract classes cannot be instantiated directly; they provide a structure for derived classes to follow. Let's examine the abstract class Car and its concrete implementations:

abstract class Car {
  String name;

  Car(this.name);

  void drive();
}
Enter fullscreen mode Exit fullscreen mode

The Car class defines an abstract method drive() that must be implemented by its subclasses.
It also declares a name property that subclasses will use to identify the car.

Concrete Implementations
Concrete classes ElectricCar and FuelCar extend the Car abstract class and provide specific implementations for the drive() method:

class ElectricCar extends Car {
  double chargeCapacity;

  ElectricCar(String name, this.chargeCapacity) : super(name);

  @override
  void drive() {
    print("Driving an Electric Car");
  }
}

class FuelCar extends Car {
  double fuelCapacity;

  FuelCar(String name, this.fuelCapacity) : super(name);

  @override
  void drive() {
    print("Driving a Fuel Car");
  }
}
Enter fullscreen mode Exit fullscreen mode

ElectricCar and FuelCar inherit the name property from the Car class and implement the drive() method with specific behaviors for electric and fuel cars.

2) Runtime Polymorphism
Runtime polymorphism allows objects to exhibit different behaviors based on their types. In the provided code, we utilize runtime polymorphism to demonstrate how different car objects respond to the drive() method:

void main() {
  final electricCars = ElectricCar('TATA', 2900);
  final fuelCars = FuelCar("BMW", 7879);
  final gasCars = GasCar("Maruti", 7879);
  final List<Car> carList = [electricCars, fuelCars, gasCars];

  for (final Car car in carList) {
    checkDrive(car);
  }
}

void checkDrive(Car car) {
  car.drive();
}

abstract class Car {
  String name;
  Car(this.name);
  void drive();
}

class ElectricCar extends Car {
  double chargeCapacity;
  ElectricCar(String name, this.chargeCapacity) : super(name);
  @override
  void drive() {
    print("Driving an Electric Car");
  }
}

class FuelCar extends Car {
  double fuelCapacity;
  FuelCar(String name, this.fuelCapacity) : super(name);
  @override
  void drive() {
    print("Driving an fuel car");
  }
}

class GasCar extends Car {
  double gasCapacity;
  GasCar(String name, this.gasCapacity) : super(name);
  @override
  void drive() {
    print("Driving an Gas car");
  }
}
Enter fullscreen mode Exit fullscreen mode

The checkDrive function takes a Car object as a parameter and invokes its drive() method, which will vary depending on the type of car object passed.

Conclusion

Abstract classes and runtime polymorphism are powerful concepts in Dart that enable code reuse, modularity, and extensibility. Dart programmers can write flexible and maintainable code that adapts to different requirements and scenarios by defining common behaviors in abstract classes and leveraging polymorphism. Understanding these concepts is essential for building robust and scalable Dart applications.

Thank you for following along with this series on Dart. Keep exploring.

🌟 Stay Connected! 🌟

Hey there, awesome reader! 👋 Want to stay updated with my latest insights,Follow me on social media!

🐦 📸 📘 💻 🌐 💼

Sadanand Gadwal

Top comments (0)