Question #362MediumOOP Concepts

Can we do Polymorphism in Flutter?

#polymorphism#oop#dart#inheritance

Answer

Overview

Yes, Flutter/Dart fully supports polymorphism! Polymorphism is one of the four pillars of Object-Oriented Programming (OOP). It allows objects of different classes to be treated as objects of a common parent class, enabling flexible and extensible code.


What is Polymorphism?

Polymorphism = "Many forms"

It means the same method or property can behave differently depending on the object that invokes it.


Types of Polymorphism

1. Compile-Time Polymorphism (Method Overloading)

Dart does NOT support method overloading (same method name with different parameters). Instead, use optional/named parameters.

dart
// ❌ Not supported in Dart
class Calculator {
  int add(int a, int b) => a + b;
  double add(double a, double b) => a + b; // Error: duplicate method
}

// ✅ Use optional/named parameters instead
class Calculator {
  num add(num a, num b) => a + b;
}

2. Runtime Polymorphism (Method Overriding)

Method overriding allows a subclass to provide a specific implementation of a method defined in its parent class.

dart
class Animal {
  void speak() {
    print('Animal makes a sound');
  }
}

class Dog extends Animal {
  
  void speak() {
    print('Dog barks: Woof!');
  }
}

class Cat extends Animal {
  
  void speak() {
    print('Cat meows: Meow!');
  }
}

void main() {
  Animal animal1 = Dog();
  Animal animal2 = Cat();

  animal1.speak(); // Output: Dog barks: Woof!
  animal2.speak(); // Output: Cat meows: Meow!
}

Key Point: The method called depends on the actual object type at runtime, not the reference type.


Polymorphism with Abstract Classes

Abstract classes define a contract that subclasses must implement.

dart
abstract class Shape {
  double area(); // Abstract method
}

class Circle extends Shape {
  final double radius;
  Circle(this.radius);

  
  double area() => 3.14159 * radius * radius;
}

class Rectangle extends Shape {
  final double width;
  final double height;
  Rectangle(this.width, this.height);

  
  double area() => width * height;
}

void printArea(Shape shape) {
  print('Area: ${shape.area()}');
}

void main() {
  printArea(Circle(5));        // Area: 78.53975
  printArea(Rectangle(4, 6));  // Area: 24.0
}

Polymorphism with Interfaces

In Dart, every class is an implicit interface. You can implement multiple interfaces using

text
implements
.

dart
abstract class Flyable {
  void fly();
}

abstract class Swimmable {
  void swim();
}

class Duck implements Flyable, Swimmable {
  
  void fly() => print('Duck is flying');

  
  void swim() => print('Duck is swimming');
}

class Airplane implements Flyable {
  
  void fly() => print('Airplane is flying');
}

void makeFly(Flyable flyable) {
  flyable.fly();
}

void main() {
  makeFly(Duck());      // Duck is flying
  makeFly(Airplane());  // Airplane is flying
}

Polymorphism in Flutter Widgets

Flutter extensively uses polymorphism through the

text
Widget
class hierarchy.

dart
class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: [
            // All are Widget types (polymorphic)
            Text('Hello'),          // StatelessWidget
            Icon(Icons.star),       // StatelessWidget
            Image.asset('logo.png'), // StatefulWidget
            Container(),            // StatelessWidget
          ],
        ),
      ),
    );
  }
}

Behind the scenes:

  • text
    Text
    ,
    text
    Icon
    ,
    text
    Image
    ,
    text
    Container
    are all subclasses of
    text
    Widget
  • text
    Column
    accepts
    text
    List<Widget>
    (polymorphism at work)

Polymorphism with Payment Example

dart
abstract class PaymentGateway {
  Future<bool> processPayment(double amount);
}

class RazorpayGateway implements PaymentGateway {
  
  Future<bool> processPayment(double amount) async {
    print('Processing ₹$amount via Razorpay');
    await Future.delayed(Duration(seconds: 2));
    return true;
  }
}

class StripeGateway implements PaymentGateway {
  
  Future<bool> processPayment(double amount) async {
    print('Processing \$$amount via Stripe');
    await Future.delayed(Duration(seconds: 2));
    return true;
  }
}

class PaymentService {
  final PaymentGateway gateway;

  PaymentService(this.gateway);

  Future<void> pay(double amount) async {
    final success = await gateway.processPayment(amount);
    if (success) {
      print('Payment successful!');
    }
  }
}

void main() async {
  // Same service, different gateways (polymorphism)
  final razorpay = PaymentService(RazorpayGateway());
  await razorpay.pay(500);

  final stripe = PaymentService(StripeGateway());
  await stripe.pay(100);
}

Operator Overloading (Special Polymorphism)

Dart allows operator overloading for custom classes.

dart
class Vector {
  final double x, y;

  Vector(this.x, this.y);

  // Overload + operator
  Vector operator +(Vector other) {
    return Vector(x + other.x, y + other.y);
  }

  // Overload * operator
  Vector operator *(double scalar) {
    return Vector(x * scalar, y * scalar);
  }

  
  String toString() => 'Vector($x, $y)';
}

void main() {
  final v1 = Vector(1, 2);
  final v2 = Vector(3, 4);

  print(v1 + v2);  // Vector(4.0, 6.0)
  print(v1 * 2);   // Vector(2.0, 4.0)
}

Polymorphism Summary Table

TypeDart SupportExample
Method Overloading❌ Not directlyUse optional parameters
Method Overriding✅ Yes
text
@override
keyword
Abstract Classes✅ Yes
text
abstract class Shape
Interfaces✅ Yes
text
implements Flyable
Operator Overloading✅ Yes
text
operator +
,
text
operator *

Benefits of Polymorphism

BenefitDescription
Code ReusabilityWrite generic code that works with multiple types
FlexibilityEasy to add new classes without changing existing code
MaintainabilityChanges in subclasses don't affect parent class
ExtensibilityAdd new behaviors by extending classes
TestabilityMock implementations for testing

Real-World Flutter Example

dart
// Base class
abstract class DataSource {
  Future<List<String>> fetchData();
}

// Remote implementation
class RemoteDataSource implements DataSource {
  
  Future<List<String>> fetchData() async {
    // Fetch from API
    await Future.delayed(Duration(seconds: 2));
    return ['Data from API'];
  }
}

// Local implementation
class LocalDataSource implements DataSource {
  
  Future<List<String>> fetchData() async {
    // Fetch from local DB
    return ['Data from DB'];
  }
}

// Mock implementation (for testing)
class MockDataSource implements DataSource {
  
  Future<List<String>> fetchData() async {
    return ['Mock Data'];
  }
}

// Repository uses polymorphism
class UserRepository {
  final DataSource dataSource;

  UserRepository(this.dataSource);

  Future<void> loadUsers() async {
    final data = await dataSource.fetchData();
    print('Loaded: $data');
  }
}

void main() async {
  // Same repository, different data sources
  final remoteRepo = UserRepository(RemoteDataSource());
  await remoteRepo.loadUsers(); // Loads from API

  final localRepo = UserRepository(LocalDataSource());
  await localRepo.loadUsers(); // Loads from DB

  final mockRepo = UserRepository(MockDataSource());
  await mockRepo.loadUsers(); // Loads mock data (for testing)
}

Summary

Yes, Dart supports polymorphism! Use method overriding with

text
@override
, abstract classes, interfaces with
text
implements
, and operator overloading. Polymorphism enables flexible, maintainable, and testable code in Flutter apps.

Learn more at Dart OOP Guide and Flutter Widget Catalog.