Question #45MediumFlutter Basics

Flutter method overriding and method overloading

#flutter

Answer

Overview

Method Overriding and Method Overloading are two different OOP concepts. Dart/Flutter supports overriding but does NOT support traditional method overloading.


Method Overriding

Definition: Subclass provides its own implementation of a method already defined in the parent class.

Example

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

  void eat() {
    print('Animal is eating');
  }
}

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

  // Inherited method (not overridden)
  // eat() works as-is from Animal
}

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

void main() {
  Animal animal = Animal();
  animal.speak(); // Animal makes a sound

  Dog dog = Dog();
  dog.speak();    // Dog barks: Woof! Woof!
  dog.eat();      // Animal is eating (inherited)

  Cat cat = Cat();
  cat.speak();    // Cat meows: Meow!
}

Rules for Overriding

  • Must have same method name
  • Must have same parameters (type and count)
  • Must have same or compatible return type
  • Use
    text
    @override
    annotation (recommended)
  • Can call parent method using
    text
    super

Calling Parent Method

dart
class Vehicle {
  void start() {
    print('Vehicle starting...');
  }
}

class Car extends Vehicle {
  
  void start() {
    super.start(); // Call parent method first
    print('Car engine started');
  }
}

void main() {
  Car car = Car();
  car.start();
  // Output:
  // Vehicle starting...
  // Car engine started
}

Method Overloading

Definition: Multiple methods with the same name but different parameters (count or type).

Important: Dart does NOT support traditional method overloading.

NOT Supported in Dart

dart
// ❌ This will NOT work in Dart
class Calculator {
  int add(int a, int b) => a + b;

  // Error: Duplicate method name
  double add(double a, double b) => a + b;

  // Error: Duplicate method name
  int add(int a, int b, int c) => a + b + c;
}

Alternatives to Method Overloading

1. Optional Parameters

dart
class Calculator {
  // Named optional parameters
  int add({required int a, required int b, int c = 0}) {
    return a + b + c;
  }
}

void main() {
  Calculator calc = Calculator();

  print(calc.add(a: 5, b: 3));        // 8
  print(calc.add(a: 5, b: 3, c: 2));  // 10
}

2. Positional Optional Parameters

dart
class Calculator {
  int add(int a, [int? b, int? c]) {
    return a + (b ?? 0) + (c ?? 0);
  }
}

void main() {
  Calculator calc = Calculator();

  print(calc.add(5));        // 5
  print(calc.add(5, 3));     // 8
  print(calc.add(5, 3, 2));  // 10
}

3. Different Method Names

dart
class Calculator {
  int addTwo(int a, int b) => a + b;
  int addThree(int a, int b, int c) => a + b + c;
  double addDoubles(double a, double b) => a + b;
}

4. Dynamic Type (Not Recommended)

dart
class Calculator {
  num add(num a, num b) {
    return a + b;
  }
}

void main() {
  Calculator calc = Calculator();

  print(calc.add(5, 3));        // 8 (int + int)
  print(calc.add(5.5, 3.2));    // 8.7 (double + double)
}

5. Named Constructors (Common Pattern)

dart
class User {
  final String name;
  final String email;

  // Default constructor
  User(this.name, this.email);

  // Named constructor - "overloading" via different names
  User.guest() : name = 'Guest', email = 'guest@example.com';

  User.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        email = json['email'];
}

void main() {
  var user1 = User('Alice', 'alice@example.com');
  var user2 = User.guest();
  var user3 = User.fromJson({'name': 'Bob', 'email': 'bob@example.com'});
}

Comparison Table

FeatureMethod OverridingMethod Overloading
Supported in Dart✅ Yes❌ No (use alternatives)
DefinitionRedefine parent methodSame name, different params
RelationshipParent-child (inheritance)Same class
Method signatureMust match parentMust differ
Keyword
text
@override
N/A
PolymorphismRuntime (dynamic)Compile-time (static)
Use caseChange behavior in subclassMultiple ways to call method

Real-World Flutter Example

Overriding in Widgets

dart
// Parent class
abstract class MyWidget extends StatelessWidget {
  Widget buildContent(BuildContext context);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('My App')),
      body: buildContent(context), // Call abstract method
    );
  }
}

// Child classes override buildContent
class HomePage extends MyWidget {
  
  Widget buildContent(BuildContext context) {
    return Center(child: Text('Home Page'));
  }
}

class ProfilePage extends MyWidget {
  
  Widget buildContent(BuildContext context) {
    return Center(child: Text('Profile Page'));
  }
}

Alternative to Overloading (Widget Constructor)

dart
class CustomButton extends StatelessWidget {
  final String text;
  final VoidCallback? onPressed;
  final Color? color;
  final IconData? icon;

  // Single constructor with optional parameters
  const CustomButton({
    required this.text,
    this.onPressed,
    this.color,
    this.icon,
  });

  // Named constructors for different "variants"
  const CustomButton.primary({
    required this.text,
    this.onPressed,
  }) : color = Colors.blue, icon = null;

  const CustomButton.icon({
    required this.text,
    required this.icon,
    this.onPressed,
  }) : color = null;

  
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      style: color != null
          ? ElevatedButton.styleFrom(backgroundColor: color)
          : null,
      child: icon != null
          ? Row(children: [Icon(icon), Text(text)])
          : Text(text),
    );
  }
}

Key Takeaways

Overriding: Supported via

text
@override
annotation. Used in inheritance to change parent behavior.

Overloading: NOT directly supported. Use optional parameters, named constructors, or different method names instead.


Resources