Parent and Child Classes in Dart – Detailed Notes with Practical Examples
Parent and child classes are important concepts of Object-Oriented Programming (OOP) in Dart. A parent class provides common properties and methods, while a child class can inherit those members and extend them with additional functionality.
In Dart, inheritance is created using the extends keyword. Parent-child class relationships are especially useful for code reuse, specialization, method overriding, and polymorphism. JustAcademy's Flutter curriculum includes Dart OOP concepts such as classes, objects, constructors, inheritance, polymorphism, and abstraction in its Dart Programming Fundamentals module. :contentReference[oaicite:0]{index=0}
Explore JustAcademy's Flutter Training
1. What is a Parent Class?
A parent class is a class whose functionality can be inherited by another class. It is also called a superclass or base class.
A parent class generally contains functionality that is common to multiple related child classes.
class Animal {
String name = 'Animal';
void eat() {
print('$name is eating');
}
}
In this example, Animal is the parent class. It contains a name property and an eat() method.
2. What is a Child Class?
A child class is a class that inherits from another class. It is also called a subclass or derived class.
Dart uses the extends keyword to create a parent-child inheritance relationship.
class Animal {
void eat() {
print('Animal is eating');
}
}
class Dog extends Animal {
void bark() {
print('Dog is barking');
}
}
Here:
Animal is the parent class.
Dog is the child class.
Dog inherits the eat() method from Animal.
Dog defines its own bark() method.
3. Parent and Child Class Relationship
Animal
|
| extends
v
Dog
The relationship can be described as:
Dog is an Animal.
This is commonly called an "is-a" relationship.
4. Basic Parent and Child Class Example
class Person {
String name = 'Amit';
void introduce() {
print('My name is $name');
}
}
class Student extends Person {
void study() {
print('$name is studying');
}
}
void main() {
Student student = Student();
student.introduce();
student.study();
}
Output:
My name is Amit
Amit is studying
The Student object can call both inherited and child-specific methods:
introduce() is inherited from Person.
study() is defined inside Student.
5. Parent Class Properties
A child class can access inherited properties when those members are accessible to the child.
class Vehicle {
String brand = 'Toyota';
int year = 2025;
}
class Car extends Vehicle {
void displayCar() {
print('Brand: $brand');
print('Year: $year');
}
}
void main() {
Car car = Car();
car.displayCar();
}
Output:
Brand: Toyota
Year: 2025
6. Parent Class Methods
A child class can use methods inherited from the parent class without redefining them.
class Vehicle {
void start() {
print('Vehicle started');
}
void stop() {
print('Vehicle stopped');
}
}
class Car extends Vehicle {
void drive() {
print('Car is driving');
}
}
void main() {
Car car = Car();
car.start();
car.drive();
car.stop();
}
Output:
Vehicle started
Car is driving
Vehicle stopped
7. Child Class Can Add Its Own Members
Inheritance does not mean that the child class is limited to the members of the parent class. A child can add its own properties and methods.
class Employee {
String name = 'Rahul';
void work() {
print('$name is working');
}
}
class Developer extends Employee {
String language = 'Dart';
void writeCode() {
print('$name is writing $language code');
}
}
void main() {
Developer developer = Developer();
developer.work();
developer.writeCode();
}
Output:
Rahul is working
Rahul is writing Dart code
8. Parent Constructor and Child Constructor
When a parent class has a constructor that requires values, the child constructor can pass values to the parent constructor using super.
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String course;
Student(
String name,
int age,
this.course,
) : super(name, age);
void display() {
print('Name: $name');
print('Age: $age');
print('Course: $course');
}
}
void main() {
Student student = Student(
'Neha',
21,
'Flutter',
);
student.display();
}
Output:
Name: Neha
Age: 21
Course: Flutter
The expression : super(name, age) calls the constructor of the parent class and initializes the inherited properties.
9. Understanding super
The super keyword is used to refer to the superclass. It is commonly used to:
- Call a parent constructor.
- Call a parent method.
- Access a parent member when needed.
Calling a Parent Method
class Animal {
void sound() {
print('Animal makes a sound');
}
}
class Dog extends Animal {
@override
void sound() {
super.sound();
print('Dog barks');
}
}
void main() {
Dog dog = Dog();
dog.sound();
}
Output:
Animal makes a sound
Dog barks
Here, super.sound() first executes the implementation from the parent class.
10. Method Overriding
Sometimes a child class needs to provide its own implementation of a method inherited from the parent class. This is called method overriding.
class Animal {
void sound() {
print('Animal makes a sound');
}
}
class Dog extends Animal {
@override
void sound() {
print('Dog barks');
}
}
void main() {
Dog dog = Dog();
dog.sound();
}
Output:
Dog barks
The @override annotation tells Dart that the child class is intentionally providing an implementation for an inherited member.
11. Parent and Child Classes with Different Behaviors
One important use of inheritance is to define general behavior in the parent class and provide specialized behavior in different child classes.
class Animal {
void sound() {
print('Animal makes a sound');
}
}
class Dog extends Animal {
@override
void sound() {
print('Dog says: Woof');
}
}
class Cat extends Animal {
@override
void sound() {
print('Cat says: Meow');
}
}
class Cow extends Animal {
@override
void sound() {
print('Cow says: Moo');
}
}
void main() {
Dog dog = Dog();
Cat cat = Cat();
Cow cow = Cow();
dog.sound();
cat.sound();
cow.sound();
}
Output:
Dog says: Woof
Cat says: Meow
Cow says: Moo
12. Parent Reference and Child Object
Dart supports polymorphism, which means a variable whose static type is a parent class can refer to an object of a child class.
class Animal {
void sound() {
print('Animal sound');
}
}
class Dog extends Animal {
@override
void sound() {
print('Dog barks');
}
}
void main() {
Animal animal = Dog();
animal.sound();
}
Output:
Dog barks
The variable is declared as Animal, but the actual object is a Dog. Therefore, the overridden implementation in Dog is executed.
13. Practical Example: Person and Student
A student is a person, so common information such as name and age can be placed in the parent class.
class Person {
String name;
int age;
Person(this.name, this.age);
void displayPerson() {
print('Name: $name');
print('Age: $age');
}
}
class Student extends Person {
int rollNumber;
String course;
Student(
String name,
int age,
this.rollNumber,
this.course,
) : super(name, age);
void displayStudent() {
displayPerson();
print('Roll Number: $rollNumber');
print('Course: $course');
}
}
void main() {
Student student = Student(
'Aman',
20,
101,
'Flutter',
);
student.displayStudent();
}
Output:
Name: Aman
Age: 20
Roll Number: 101
Course: Flutter
14. Practical Example: Employee and Developer
class Employee {
String name;
double salary;
Employee(this.name, this.salary);
void displayEmployee() {
print('Employee: $name');
print('Salary: ₹$salary');
}
}
class Developer extends Employee {
String programmingLanguage;
Developer(
String name,
double salary,
this.programmingLanguage,
) : super(name, salary);
void develop() {
print('$name is developing using $programmingLanguage');
}
}
void main() {
Developer developer = Developer(
'Ravi',
60000,
'Dart',
);
developer.displayEmployee();
developer.develop();
}
Output:
Employee: Ravi
Salary: ₹60000.0
Ravi is developing using Dart
15. Practical Example: Vehicle and Car
class Vehicle {
String brand;
int speed;
Vehicle(this.brand, this.speed);
void displayVehicle() {
print('Brand: $brand');
print('Speed: $speed km/h');
}
void start() {
print('$brand has started');
}
}
class Car extends Vehicle {
int doors;
Car(
String brand,
int speed,
this.doors,
) : super(brand, speed);
void displayCar() {
displayVehicle();
print('Doors: $doors');
}
}
void main() {
Car car = Car(
'Honda',
180,
4,
);
car.start();
car.displayCar();
}
Output:
Honda has started
Brand: Honda
Speed: 180 km/h
Doors: 4
16. Practical Example: Bank Account
class BankAccount {
String accountHolder;
double balance;
BankAccount(this.accountHolder, this.balance);
void deposit(double amount) {
balance += amount;
print('Deposited: ₹$amount');
}
void showBalance() {
print('Balance: ₹$balance');
}
}
class SavingsAccount extends BankAccount {
double interestRate;
SavingsAccount(
String accountHolder,
double balance,
this.interestRate,
) : super(accountHolder, balance);
void addInterest() {
double interest =
balance * interestRate / 100;
balance += interest;
print('Interest added: ₹$interest');
}
}
void main() {
SavingsAccount account = SavingsAccount(
'Priya',
10000,
5,
);
account.deposit(2000);
account.addInterest();
account.showBalance();
}
Here, SavingsAccount inherits common banking functionality from BankAccount and adds its own interest-related functionality.
17. Practical Example: Product and Electronics Product
In an e-commerce application, multiple products can share common properties such as name and price. Specialized product classes can inherit those common properties.
class Product {
String name;
double price;
Product(this.name, this.price);
void displayProduct() {
print('Product: $name');
print('Price: ₹$price');
}
}
class ElectronicsProduct extends Product {
int warrantyYears;
ElectronicsProduct(
String name,
double price,
this.warrantyYears,
) : super(name, price);
void displayWarranty() {
print('Warranty: $warrantyYears years');
}
}
void main() {
ElectronicsProduct laptop = ElectronicsProduct(
'Laptop',
65000,
2,
);
laptop.displayProduct();
laptop.displayWarranty();
}
Output:
Product: Laptop
Price: ₹65000.0
Warranty: 2 years
18. Practical Example: User and Admin
A common application design is to have a general User class and a specialized Admin child class.
class User {
String username;
String email;
User(this.username, this.email);
void login() {
print('$username logged in');
}
void displayProfile() {
print('Username: $username');
print('Email: $email');
}
}
class Admin extends User {
List permissions;
Admin(
String username,
String email,
this.permissions,
) : super(username, email);
void showPermissions() {
print('Permissions: $permissions');
}
void deleteUser() {
print('Admin can delete users');
}
}
void main() {
Admin admin = Admin(
'admin01',
'[email protected]',
['create', 'edit', 'delete'],
);
admin.login();
admin.displayProfile();
admin.showPermissions();
admin.deleteUser();
}
Output:
admin01 logged in
Username: admin01
Email: [email protected]
Permissions: [create, edit, delete]
Admin can delete users
19. Practical Example: Shape Hierarchy
class Shape {
void draw() {
print('Drawing shape');
}
}
class Circle extends Shape {
double radius;
Circle(this.radius);
double area() {
return 3.14 * radius * radius;
}
}
class Rectangle extends Shape {
double width;
double height;
Rectangle(this.width, this.height);
double area() {
return width * height;
}
}
void main() {
Circle circle = Circle(5);
Rectangle rectangle = Rectangle(10, 5);
circle.draw();
print('Circle area: ${circle.area()}');
rectangle.draw();
print('Rectangle area: ${rectangle.area()}');
}
Output:
Drawing shape
Circle area: 78.5
Drawing shape
Rectangle area: 50.0
20. Parent and Child Classes in Flutter
Understanding inheritance is particularly useful in Flutter because Flutter development uses Dart's object-oriented features extensively. JustAcademy's curriculum places Dart OOP concepts such as inheritance and polymorphism in the Dart Programming Fundamentals module and then introduces Flutter widgets and UI design. :contentReference[oaicite:1]{index=1}
Example with StatelessWidget
import 'package:flutter/material.dart';
class WelcomeScreen extends StatelessWidget {
const WelcomeScreen({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text(
'Welcome to Flutter',
),
),
);
}
}
In this example, WelcomeScreen extends StatelessWidget. The build() method is overridden to describe the widget's UI.
21. Understanding super.key in Flutter
class MyScreen extends StatelessWidget {
const MyScreen({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('My Screen'),
),
);
}
}
Important concepts in this example include:
StatelessWidget is the superclass being extended.
MyScreen is the child class.
extends establishes the inheritance relationship.
@override indicates that build() is being overridden.
super.key forwards the key parameter to the superclass constructor.
22. Multilevel Parent and Child Classes
Multilevel inheritance occurs when a class inherits from another child class, creating multiple levels of inheritance.
class Animal {
void eat() {
print('Eating');
}
}
class Mammal extends Animal {
void breathe() {
print('Breathing');
}
}
class Dog extends Mammal {
void bark() {
print('Barking');
}
}
void main() {
Dog dog = Dog();
dog.eat();
dog.breathe();
dog.bark();
}
The inheritance structure is:
Animal
|
v
Mammal
|
v
Dog
The Dog object can access methods from both Mammal and Animal.
23. Multiple Child Classes from One Parent
Dart allows multiple classes to extend the same parent class. This creates a hierarchical inheritance structure.
class Employee {
void work() {
print('Employee is working');
}
}
class Developer extends Employee {
void code() {
print('Developer is coding');
}
}
class Designer extends Employee {
void design() {
print('Designer is designing');
}
}
void main() {
Developer developer = Developer();
Designer designer = Designer();
developer.work();
developer.code();
designer.work();
designer.design();
}
The structure is:
Employee
/ \
/ \
Developer Designer
24. Parent Class vs Child Class
| Feature |
Parent Class |
Child Class |
| Purpose |
Provides common functionality. |
Reuses and extends parent functionality. |
| Other Name |
Superclass / Base class |
Subclass / Derived class |
| Inheritance |
Can be inherited by another class. |
Inherits from another class. |
| New Features |
Defines common features. |
Can add specialized features. |
| Method Overriding |
Provides the inherited implementation. |
Can provide a specialized implementation. |
super |
Represents the superclass when referenced from a subclass. |
Can use super to access superclass functionality. |
25. Parent Class vs Child Class Example
class Animal {
// Parent class
void eat() {
print('Eating');
}
}
class Dog extends Animal {
// Child class
void bark() {
print('Barking');
}
}
| Code |
Meaning |
eat() |
Method defined by the parent class. |
bark() |
Method defined by the child class. |
extends Animal |
Creates the inheritance relationship. |
Dog() |
Creates an object of the child class. |
26. Advantages of Parent and Child Classes
- Code Reusability: Common functionality can be written once in the parent class.
- Less Code Duplication: Child classes can reuse inherited methods and properties.
- Easy Maintenance: Shared functionality can be maintained in one place.
- Extensibility: Child classes can add specialized functionality.
- Polymorphism: Parent types can refer to objects of child classes.
- Better Organization: Related classes can be organized into meaningful hierarchies.
- Flutter Understanding: It helps developers understand inheritance relationships used throughout Dart and Flutter development.
27. When Should You Use Parent and Child Classes?
Inheritance is generally appropriate when there is a meaningful "is-a" relationship between the classes.
Examples include:
- Dog is an Animal.
- Car is a Vehicle.
- Student is a Person.
- Developer is an Employee.
- Admin is a User.
- ElectronicsProduct is a Product.
28. Inheritance vs Composition
Not every relationship should be implemented through inheritance. When one class contains or uses another object, composition may be more appropriate.
Inheritance – "Is-a"
class Vehicle {}
class Car extends Vehicle {}
A car is a vehicle.
Composition – "Has-a"
class Engine {
void start() {
print('Engine started');
}
}
class Car {
Engine engine = Engine();
void startCar() {
engine.start();
}
}
A car has an engine.
| Inheritance |
Composition |
| Represents an "is-a" relationship. |
Represents a "has-a" relationship. |
Uses extends. |
Uses object references. |
| Child inherits parent behavior. |
Class uses functionality supplied by another object. |
| Useful for genuine class hierarchies. |
Useful when behavior can be assembled from separate components. |
29. Common Mistakes
Mistake 1: Forgetting extends
Incorrect:
class Dog {
}
Correct:
class Dog extends Animal {
}
Mistake 2: Incorrect Parent Constructor Initialization
class Person {
String name;
Person(this.name);
}
class Student extends Person {
Student(String name) : super(name);
}
The child constructor explicitly passes the required value to the parent constructor.
Mistake 3: Forgetting @override
While Dart can recognize an override without the annotation in valid cases, using @override makes the programmer's intention clear and allows the analyzer to check that the member actually overrides an inherited member.
Mistake 4: Using Inheritance Only for Code Reuse
Inheritance creates a relationship between classes. If there is no meaningful "is-a" relationship, consider composition or another design approach.
30. Best Practices
- Keep parent classes focused on genuinely shared functionality.
- Use
extends when the inheritance relationship makes conceptual sense.
- Use
@override when overriding inherited methods.
- Use
super when parent behavior or constructor initialization is required.
- Avoid unnecessarily deep inheritance hierarchies.
- Prefer composition when the relationship is "has-a" rather than "is-a".
- Use inheritance together with polymorphism when specialized child behavior is required.
- Keep child classes focused on their specialized responsibilities.
31. Quick Revision Program
class Person {
String name;
Person(this.name);
void introduce() {
print('Hello, I am $name');
}
}
class Student extends Person {
String course;
Student(
String name,
this.course,
) : super(name);
@override
void introduce() {
super.introduce();
print('I am studying $course');
}
}
void main() {
Student student = Student(
'Rahul',
'Flutter',
);
student.introduce();
}
Output:
Hello, I am Rahul
I am studying Flutter
32. Important Keywords and Concepts
| Keyword / Concept |
Purpose |
Example |
extends |
Creates a class inheritance relationship. |
class Dog extends Animal |
super |
References the superclass. |
super.sound() |
@override |
Marks an inherited member that is being overridden. |
@override void sound() |
| Parent Class |
Provides common functionality. |
Animal |
| Child Class |
Inherits and can extend functionality. |
Dog |
| Polymorphism |
Allows child objects to be handled through parent types. |
Animal animal = Dog() |
33. Practice Exercises
- Create a
Person parent class and a Student child class.
- Create an
Animal parent class with Dog, Cat, and Cow child classes.
- Override the
sound() method in each child class.
- Create an
Employee parent class with Developer and Designer child classes.
- Use a parent constructor and pass values using
super.
- Use
super to call a parent method from a child class.
- Create a
Product parent class and an ElectronicsProduct child class.
- Create a
User parent class and an Admin child class.
- Create a Flutter
StatelessWidget and identify its parent class and overridden method.
- Create a multilevel inheritance example using
Animal, Mammal, and Dog.
34. Interview Questions
- What is a parent class in Dart?
- What is a child class?
- Which keyword is used for inheritance in Dart?
- What is the difference between a superclass and a subclass?
- What is the purpose of the
super keyword?
- What is method overriding?
- Why is
@override used?
- Can a child class add its own properties and methods?
- How does a child class call a parent constructor?
- What is the difference between inheritance and composition?
- What is multilevel inheritance?
- How is polymorphism related to parent and child classes?
- How is inheritance used in Flutter widgets?
35. Key Takeaways
- A parent class provides common properties and methods.
- A child class inherits from the parent class.
- Dart uses the
extends keyword for class inheritance.
- A child class can use inherited properties and methods.
- A child class can add its own properties and methods.
- A child class can override inherited methods.
@override is used to identify an overridden member.
super can be used to access superclass functionality and constructors.
- Parent initialization takes place as part of constructing a child object before the child constructor body executes.
- Parent and child classes can be used to implement polymorphic behavior.
- Inheritance generally represents an "is-a" relationship.
- Composition generally represents a "has-a" relationship.
- Understanding inheritance is useful for learning Dart OOP and working with Flutter's class-based widget system.
36. Learn Flutter with JustAcademy
JustAcademy's Flutter training curriculum includes Dart Programming Fundamentals with OOP, classes, objects, constructors, inheritance, polymorphism, and abstraction, followed by Flutter Widgets and UI Design. :contentReference[oaicite:2]{index=2}
View JustAcademy Flutter Training
Register for JustAcademy Course Demo