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
dartclass 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 annotation (recommended)text
@override - Can call parent method using text
super
Calling Parent Method
dartclass 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
dartclass 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
dartclass 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
dartclass 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)
dartclass 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)
dartclass 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
| Feature | Method Overriding | Method Overloading |
|---|---|---|
| Supported in Dart | ✅ Yes | ❌ No (use alternatives) |
| Definition | Redefine parent method | Same name, different params |
| Relationship | Parent-child (inheritance) | Same class |
| Method signature | Must match parent | Must differ |
| Keyword | text | N/A |
| Polymorphism | Runtime (dynamic) | Compile-time (static) |
| Use case | Change behavior in subclass | Multiple 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)
dartclass 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
annotation. Used in inheritance to change parent behavior.text@override
Overloading: NOT directly supported. Use optional parameters, named constructors, or different method names instead.