Skip to content

Classes and Inheritance

Dart is an object-oriented language with single inheritance. Every class implicitly extends Object. Unlike Java, Dart has no interfaces as a separate construct — classes themselves serve as Interfaces.

class User {
// Fields (instance variables)
final String name;
int _age; // Private (by convention, prefix with _)
String email;
// Constructor
User({
required this.name,
required int age,
required this.email,
}) : _age = age;
// Named constructor
User.guest()
: name = "Guest',
_age = 0,
email = '';
// Factory constructor (returns an instance, does not always create new)
factory User.fromJson(Map<String, dynamic> json) {
return User(
name: json['name'] as String,
age: json['age'] as int,
email: json['email'] as String,
);
}
// Getter
int get age => _age;
// Setter
set age(int value) {
if (value < 0) throw ArgumentError('Age cannot be negative');
_age = value;
}
// Method
String greet() => 'Hello, I\'m $name';
}

Dart provides several constructor patterns:

import 'dart:math';
class Point {
final double x;
final double y;
// Generative constructor (default)
Point(this.x, this.y);
// Named constructor
Point.origin() : x = 0, y = 0;
// Redirecting constructor
Point.alongX(double x) : this(x, 0);
// Constant constructor (compile-time constant)
const Point.zero() : x = 0, y = 0;
// Factory constructor
factory Point.polar(double r, double theta) {
return Point(r * cos(theta), r * sin(theta));
}
}
flowchart TD
    A["Generative<br/>Point(this.x, this.y)"] --> B["Named<br/>Point.origin()"]
    A --> C["Redirecting<br/>Point.alongX(x)"]
    A --> D["Constant<br/>const Point.zero()"]
    A --> E["Factory<br/>factory Point.polar(r, θ)"]

    B -.->|"delegates to"| A
    C -.->|"redirects to"| A
    D -.->|"compile-time"| A
    E -.->|"returns"| A

    style E fill:#fff3e0
    style D fill:#e8f5e9

The initializer list runs before the constructor body and can be used to:

  1. Initialize final fields.
  2. Assert preconditions.
  3. Call the superclass constructor.
class Rectangle {
final double width;
final double height;
final double area;
// area is computed from width and height before the body runs
Rectangle(double width, double height)
: this.width = width,
this.height = height,
area = width * height,
assert(width > 0, 'Width must be positive'),
assert(height > 0, 'Height must be positive');
}