Answer
Overview
The @override annotation in Flutter/Dart indicates that a method is intentionally overriding a method from a parent class or interface. It's a marker that helps catch errors and improves code readability.
Purpose of @override
1. Documentation
Clearly shows which methods are inherited and overridden.
dartclass Animal { void makeSound() { print('Some sound'); } } class Dog extends Animal { void makeSound() { print('Bark!'); } }
2. Error Prevention
Catches typos and signature mismatches at compile time.
dartclass Parent { void doSomething() {} } class Child extends Parent { void doSomthing() {} // ❌ Compile error: no method to override }
Without @override, the typo would create a new method instead of overriding.
3. Maintainability
If parent method changes or is removed, you get warnings.
Common Use Cases in Flutter
1. Widget build() Method
dartclass MyWidget extends StatelessWidget { Widget build(BuildContext context) { return Container(); } }
2. State Lifecycle Methods
dartclass _MyWidgetState extends State<MyWidget> { void initState() { super.initState(); // Initialization code } void dispose() { // Cleanup code super.dispose(); } Widget build(BuildContext context) { return Container(); } }
3. Inherited Widget Methods
dartclass MyInheritedWidget extends InheritedWidget { bool updateShouldNotify(MyInheritedWidget oldWidget) { return true; } }
4. Custom Painter
dartclass MyPainter extends CustomPainter { void paint(Canvas canvas, Size size) { // Painting code } bool shouldRepaint(CustomPainter oldDelegate) { return false; } }
Complete Example
dart// Parent class abstract class Shape { String name; Shape(this.name); double calculateArea(); void describe() { print('This is a $name'); } } // Child class with overrides class Circle extends Shape { double radius; Circle(this.radius) : super('Circle'); double calculateArea() { return 3.14159 * radius * radius; } void describe() { super.describe(); // Call parent method print('Radius: $radius'); } } void main() { final circle = Circle(5.0); circle.describe(); print('Area: ${circle.calculateArea()}'); }
Override vs Overload
| Feature | Override | Overload |
|---|---|---|
| Definition | Replace parent method | Multiple methods same name |
| Signature | Same as parent | Different parameters |
| Annotation | @override | Not supported in Dart |
| Inheritance | Required | Not required |
| Runtime | Dynamic dispatch | Compile-time resolution |
dart// ✅ Override (supported) class Parent { void greet() => print('Hi'); } class Child extends Parent { void greet() => print('Hello'); // Same signature } // ❌ Overload (NOT supported in Dart) class Calculator { int add(int a, int b) => a + b; // Can't have another add() with different params // double add(double a, double b) => a + b; // ❌ Error } // ✅ Alternative: Named methods or optional parameters class Calculator { int add(int a, int b) => a + b; double addDouble(double a, double b) => a + b; // Or use optional parameters num sum(num a, num b, [num c = 0]) => a + b + c; }
Best Practices
Important: Always use @override when overriding methods
✅ Do
dartclass MyWidget extends StatelessWidget { // Always add this Widget build(BuildContext context) { return Container(); } }
❌ Don't
dartclass MyWidget extends StatelessWidget { // Missing @override - harder to maintain Widget build(BuildContext context) { return Container(); } }
Call super When Needed
dartvoid initState() { super.initState(); // ✅ Required // Your initialization } void dispose() { // Your cleanup super.dispose(); // ✅ Required (at end) }
Key Points
- @override is optional but highly recommended
- Helps catch errors at compile time
- Makes code more readable and maintainable
- Required for abstract method implementations
- Use with Flutter lifecycle methods (build, initState, dispose)
- Dart doesn't support method overloading