YouTip LogoYouTip

Dart Inheritance

Inheritance is one of the three main features of object-oriented programming. It allows a class to be based on another class for extension. This chapter introduces Dart's extends single inheritance, method overriding, super keyword, and abstract classes. * * * ## extends Single Inheritance Dart only supports single inheritance β€” each class can have only one direct parent class. However, the inheritance chain can be long: child class inherits from parent class, parent class inherits from grandparent class, and so on. ## Example // Parent class (base class, superclass) class Animal { String name; Animal(this.name); void eat(){ print('$name is eating'); } void sleep(){ print('$name is sleeping'); } } // Subclass: inherits from Animal using extends class Dog extends Animal { String breed;// Breed // Subclass constructor needs to call parent constructor Dog(String name,this.breed):super(name); // New method added by subclass void bark(){ print('$name ($breed) is barking!'); } } void main(){ var dog = Dog('Wangcai','Golden Retriever'); // Call methods inherited from parent class dog.eat(); dog.sleep(); // Call subclass's own method dog.bark(); // Subclass object is also a parent type Animal animal = dog;// Dog is Animal, can be upcast animal.eat(); } Wangcai is eatingWangcai is sleepingWangcai (Golden Retriever) is barking!Wangcai is eating Subclass can access all non-private member variables and methods in the parent class. Private members (starting with underscore) will not be inherited. > Dart does not have public, protected, private keywords. Members starting with underscore (_) are library-private and can only be accessed within the same file. This is different from Java/C++ access control. * * * ## Method Overriding @override Subclass can override (override) methods in the parent class to provide its own implementation. Use the @override annotation to explicitly indicate the overriding intent, and the compiler will help you check if it's correctly overridden. ## Example class Animal { String name; Animal(this.name); // Parent class method void makeSound(){ print('$name makes some sounds'); } @override String toString(){ return'Animal: $name'; } } class Cat extends Animal { Cat(String name):super(name); // @override annotation: tells compiler I'm overriding parent method @override void makeSound(){ print('$name meows~'); } } class Duck extends Animal { Duck(String name):super(name); @override void makeSound(){ print('$name quacks!'); } } void main(){ var cat = Cat('Xiaohua'); var duck = Duck('Donald'); cat.makeSound(); duck.makeSound(); // Polymorphism: same method, different objects have different behaviors List animals =[ Cat('Mimi'), Duck('Yaya'), Cat('Qiuqiu'), ]; print('--- TUTORIAL Zoo ---'); for(var animal in animals){ animal.makeSound();// At runtime, calls the actual type's method } } Xiaohua meows~Donald quacks!--- TUTORIAL Zoo ---Mimi meows~Yaya quacks!Qiuqiu meows~ The example above demonstrates Polymorphism: the same method call animal.makeSound(), the actual behavior executed depends on the object's real type. > Using @override annotation has two benefits: first, it makes the code intent clearer, second, if the parent class doesn't have a method with the same name (e.g., typo), the compiler will report an error. It is recommended to always add @override. * * * ## super Keyword super represents the parent class object, and subclasses use super to call the parent class's constructor, methods, and properties. ## Example class Vehicle { String brand; int year; Vehicle(this.brand,this.year); void start(){ print('$brand vehicle started'); } void displayInfo(){ print('Brand: $brand, Year: $year'); } } class ElectricCar extends Vehicle { int batteryLevel; ElectricCar(String brand,int year,this.batteryLevel) :super(brand, year);// Call parent class constructor @override void start(){ // Call parent class method in subclass method super.start();// First execute parent class's startup logic print('Battery level: $batteryLevel%'); print('Electric motor silent start complete'); } @override void displayInfo(){ super.displayInfo();// First display parent class's basic info print('Battery level: $batteryLevel%');// Then add subclass's specific info } } void main(){ var car = ElectricCar('TUTORIAL EV',2026,85); car.start(); print('---'); car.displayInfo(); } TUTORIAL EV vehicle startedBattery level: 85%Electric motor silent start complete---Brand: TUTORIAL EV, Year: 2026Battery level: 85% ### super Usage Scenarios Summary | Scenario | Syntax | Description | | --- | --- | --- | | Call parent constructor | : super(args) | Must be called in initializer list | | Call parent method | super.methodName() | Can be called in subclass override method | | Access parent property | super.propertyName | Access parent class's member variable | * * * ## Abstract Class abstract Abstract classes are classes that cannot be directly instantiated. They only define interface specifications, and subclasses implement the specific logic. ## Example // abstract keyword to declare abstract class abstract class Shape { // Abstract method: no method body, subclass must implement double getArea(); double getPerimeter(); // Abstract class can also have concrete methods void describe(){ print('This is a shape, area: ${getArea()}, perimeter: ${getPerimeter()}'); } } class Rectangle extends Shape { double width; double height; Rectangle(this.width,this.height); @override double getArea()=> width * height; @override double getPerimeter()=>2*(width + height); } class Circle extends Shape { double radius; Circle(this.radius); @override double getArea()=>3.14159* radius * radius; @override double getPerimeter()=>2*3.14159* radius; } void main(){ // Shape shape = Shape(); // Error! Abstract class cannot be instantiated var rect = Rectangle(10,5); var circle = Circle(7); rect.describe(); circle.describe(); // Use abstract class as type List shapes =[ Rectangle(3,4), Circle(5), Rectangle(6,2), ]; print('--- TUTORIAL Shape Statistics ---'); double totalArea =0; for(var shape in shapes){ totalArea += shape.getArea(); } print('Total area: ${totalArea.toStringAsFixed(2)}'); } This is a shape, area: 50.0, perimeter: 30.0This is a shape, area: 153.93791, perimeter: 43.
← Dart GenericsDart Functions β†’