Dart Class

A Dart class is a blueprint for creating objects. It groups data in fields and behavior in methods, and it can define constructors that control how objects are initialized.

This tutorial explains Dart class syntax, object creation, instance fields, methods, constructors, named constructors, getters, setters, static members, inheritance, and null-safe class design.

Dart Class Syntax

A class can contain variables (properties), constructors and methods (behavior). class keyword is used to define a class in Dart.

Following is the syntax of a Dart Class.

</>
Copy
 class ClassName {
   //variables
   //constructor
   //named constructors
   //methods
 }

Here, ClassName is the identifier used to refer to the class. Dart style conventions normally use UpperCamelCase for class names and lowerCamelCase for fields and methods.

Dart Class with Instance Variables

Let us define a simple Dart Class with just variables.

</>
Copy
class Car{
  String name;
  int miles;
}

This class has two variables: one is of type String and the other is of type integer.

The example above uses pre-null-safety syntax. In current Dart, a non-nullable instance field must receive a value before the constructor body finishes. You can initialize fields through constructor parameters, assign a default value, or mark a field nullable when the absence of a value is valid.

</>
Copy
class Car {
  String name;
  int miles;

  Car(this.name, this.miles);
}

Dart Class with Variables and Methods

Let us define a simple Dart Class with variables and methods.

</>
Copy
class Car{
  String name;
  int miles;
  
  void printDetails() {
    print(name+' has gone '+miles.toString()+' miles.');
  }
}

This class has two variables and one method. The method is printDetails().

An instance method can read or update the fields of the object on which it is called. Inside an instance method, this refers to the current object, although Dart usually lets you omit this. when there is no naming conflict.

Create and Use a Dart Class Object

You can create multiple objects from the same class. Each object stores its own instance-field values. Use the dot operator to access a field or call a method.

Let us the Car class we defined in the previous example and create an object, access the variables and call methods.

example.dart

</>
Copy
class Car{
  String name;
  int miles;
  
  void printDetails() {
    print(name+' has gone '+miles.toString()+' miles.');
  }
}

void main(){
  //create obejct
  Car car = Car();
  
  //set variables
  car.name = 'Ford Mustang';
  car.miles = 22000;
  
  //call method
  car.printDetails();
}

Output

Ford Mustang has gone 22000 miles.

With null safety, initialize the required fields when the object is created:

</>
Copy
class Car {
  String name;
  int miles;

  Car(this.name, this.miles);

  void printDetails() {
    print('$name has gone $miles miles.');
  }
}

void main() {
  final car = Car('Ford Mustang', 22000);
  car.printDetails();
}

The final keyword prevents the variable car from referring to another object. It does not make every field inside the Car object immutable.

Dart Class Constructor

A constructor shares the syntax of a method, with same name as that of class and without any return type.

When you create an object of a class type, you can provide the values for parameters given in a constructor.

</>
Copy
class Car{
  String name;
  int miles;
  
  Car(name, miles) {
    this.name = name;
    this.miles = miles;
  }
}

The number of parameters you provide for a constructor are your choice.

Let us see an example of class using constructor.

Dart Program – example.dart

</>
Copy
class Car{
  //variables
  String name;
  int miles;
  
  //constructor
  Car(name, miles) {
    this.name = name;
    this.miles = miles;
  }
  
  //method
  void printDetails() {
    print(name+' has gone '+miles.toString()+' miles.');
  }
}


void main(){
  //create obejct
  Car car = Car('Ford Mustang', 22320);
  
  //call method
  car.printDetails();
}

Output

Ford Mustang has gone 22320 miles.

Dart provides initializing formals, which reduce repetitive assignments such as this.name = name. The following constructor initializes both fields directly:

</>
Copy
class Car {
  String name;
  int miles;

  Car(this.name, this.miles);
}

Named and Optional Constructor Parameters

Named parameters make object creation easier to read. Add required when the caller must supply a non-nullable named parameter. Optional parameters can use default values.

</>
Copy
class Car {
  final String name;
  int miles;

  Car({
    required this.name,
    this.miles = 0,
  });
}

void main() {
  final car = Car(name: 'Ford Mustang', miles: 1200);
  print('${car.name}: ${car.miles} miles');
}

Dart Named Constructors

You can define special type of constructors called named constructors in a class. The name of this named constructor is followed after the class name with a dot in the definition.

An example is shown below, where in we defined a named constructor, along with a standard constructor for class Car.

Dart Program – example.dart

</>
Copy
class Car{
  //variables
  String name;
  int miles;
  
  //constructor
  Car(name, miles) {
    this.name = name;
    this.miles = miles;
  }
  
  //named constructor
  Car.fromName(name){
    this.name = name;
	this.miles = 10000;
  }
  
  //method
  void printDetails() {
    print(name+' has gone '+miles.toString()+' miles.');
  }
}


void main(){
  //create obejct
  Car car = Car.fromName('Ford Mustang');
  
  //call method
  car.printDetails();
}

Output

Ford Mustang has gone 10000 miles.

A named constructor is useful when a class needs more than one meaningful creation path. For example, one constructor can accept complete data while another supplies a standard starting mileage.

</>
Copy
class Car {
  final String name;
  int miles;

  Car(this.name, this.miles);

  Car.newCar(this.name) : miles = 0;

  Car.used(this.name, {required this.miles});
}

void main() {
  final newCar = Car.newCar('Ford Mustang');
  final usedCar = Car.used('Ford Focus', miles: 48000);

  print(newCar.miles);
  print(usedCar.miles);
}

Getters and Setters in a Dart Class

Getters expose a calculated or controlled value as if it were a property. Setters validate or transform a value before storing it. A leading underscore makes a name library-private in Dart.

</>
Copy
class Car {
  final String name;
  int _miles;

  Car(this.name, this._miles);

  int get miles => _miles;

  set miles(int value) {
    if (value < 0) {
      throw ArgumentError('Mileage cannot be negative.');
    }
    _miles = value;
  }

  bool get isHighMileage => _miles >= 100000;
}

Static Fields and Methods in Dart Classes

A static member belongs to the class itself rather than to an individual object. Access it with the class name. Static methods cannot directly access instance fields because no particular object is available.

</>
Copy
class DistanceConverter {
  static const double milesToKilometers = 1.609344;

  static double toKilometers(double miles) {
    return miles * milesToKilometers;
  }
}

void main() {
  print(DistanceConverter.toKilometers(10));
}

Inheritance and Method Overriding in Dart

Use extends to derive one class from another. The child class inherits accessible members and can replace inherited behavior with an overridden method. The @override annotation helps tools verify that a matching superclass member exists.

</>
Copy
class Vehicle {
  final String name;

  Vehicle(this.name);

  void describe() {
    print('Vehicle: $name');
  }
}

class ElectricCar extends Vehicle {
  final int batteryCapacity;

  ElectricCar(super.name, this.batteryCapacity);

  @override
  void describe() {
    print('$name has a $batteryCapacity kWh battery.');
  }
}

Immutable Dart Class with const Constructor

A class can provide a const constructor when all instance fields are final and the object can be created as a compile-time constant. Equal constant expressions may refer to the same canonical object.

</>
Copy
class Point {
  final int x;
  final int y;

  const Point(this.x, this.y);
}

void main() {
  const first = Point(2, 3);
  const second = Point(2, 3);

  print(identical(first, second));
}

Output

true

Dart Class Design Notes

  • Initialize every non-nullable field before construction completes.
  • Use final for fields that should not be reassigned after object creation.
  • Use named parameters when several arguments of similar types would otherwise be difficult to read.
  • Keep validation close to the class by using constructors, setters, or dedicated methods.
  • Use named constructors for distinct creation paths, such as parsing, defaults, or alternate input formats.
  • Prefer small classes with a clear responsibility instead of placing unrelated behavior in one class.

Dart Class Questions

What is the difference between a class and an object in Dart?

A class defines the fields, methods, and constructors that a type provides. An object is a runtime instance created from that class, with its own instance-field values.

Can a Dart class have more than one constructor?

Yes. A class can have one unnamed constructor and multiple named constructors. Dart does not overload constructors solely by changing parameter lists, so named constructors provide distinct constructor names.

Why does Dart report that a non-nullable field must be initialized?

Null safety requires a non-nullable instance field to have a value before the constructor finishes. Initialize it at its declaration, through an initializing formal such as this.name, in an initializer list, or use late only when initialization is guaranteed before access.

When should a Dart class use a factory constructor?

Use a factory constructor when object creation may return an existing instance, return an instance of a subtype, perform caching, or require logic that cannot be completed by a generative constructor alone.

Summary of Dart Classes

In this Dart Tutorial, we have learned how to define a class in Dart, structure of a Dart Class, how to create objects of a class type, constructors and named constructors for a class. We also covered null-safe field initialization, getters, setters, static members, inheritance, method overriding, and immutable classes with const constructors.