flutter
/

Dart Constructors – Complete Guide with Examples

Last Sync: Today

On this page

12
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

Dart Constructors – Complete Guide with Examples

What is a Constructor?

A constructor is a special method used to initialize an object when it is created. It has the same name as the class and no return type. Dart provides several types of constructors to give you flexibility in how objects are created and initialized.

  1. Default Constructor

If you don't define a constructor, Dart provides a default constructor with no arguments. It doesn't do anything but allows you to create an instance.

DARTRead-only
1
class Person {
  String name = '';
  int age = 0;
}

void main() {
  var p = Person(); // default constructor called
}

  1. Parameterized Constructor

You can define a constructor that takes parameters to set initial values. The most concise syntax uses this.property in the parameter list.

DARTRead-only
1
class Person {
  String name;
  int age;

  Person(this.name, this.age);
}

void main() {
  var p = Person('Alice', 30);
}

  1. Named Constructors

Named constructors allow a class to have multiple constructors with different names. They are useful for providing different ways to create an object.

DARTRead-only
1
class Person {
  String name;
  int age;

  Person(this.name, this.age);

  Person.guest() {
    name = 'Guest';
    age = 18;
  }

  Person.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        age = json['age'];
}

void main() {
  var p1 = Person('Bob', 25);
  var p2 = Person.guest();
  var p3 = Person.fromJson({'name': 'Charlie', 'age': 28});
}

  1. Redirecting Constructors

A redirecting constructor delegates its work to another constructor in the same class. It has an empty body and uses this followed by the target constructor.

DARTRead-only
1
class Point {
  int x, y;

  Point(this.x, this.y);

  // Redirects to the main constructor
  Point.origin() : this(0, 0);
}

void main() {
  var p = Point.origin(); // x=0, y=0
}

  1. Constant Constructors

If a class produces objects that never change, you can make its constructor const. This allows the objects to be compile‑time constants, saving memory and improving performance.

DARTRead-only
1
class ImmutablePoint {
  final int x, y;

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

void main() {
  var p1 = const ImmutablePoint(1, 2);
  var p2 = const ImmutablePoint(1, 2);
  print(identical(p1, p2)); // true (same instance)
}

All fields must be final for a constant constructor to work.

  1. Factory Constructors

A factory constructor doesn't always create a new instance. It can return an existing instance (e.g., from a cache) or an instance of a subtype. It uses the factory keyword.

DARTRead-only
1
class Logger {
  final String name;
  static final Map<String, Logger> _cache = {};

  factory Logger(String name) {
    return _cache.putIfAbsent(name, () => Logger._internal(name));
  }

  Logger._internal(this.name);
}

void main() {
  var log1 = Logger('UI');
  var log2 = Logger('UI');
  print(identical(log1, log2)); // true (same cached instance)
}

Factory constructors are also commonly used to implement the singleton pattern or to perform complex initialization before returning an instance.

Initializer List

You can add an initializer list before the constructor body to initialize fields, assert conditions, or call super constructors. It's separated by a colon :.

DARTRead-only
1
class Person {
  String name;
  int age;

  Person(String name, int age)
      : assert(age >= 0),
        name = name,
        age = age;
}

void main() {
  var p = Person('Alice', 30);
}

Calling Superclass Constructors

By default, a constructor calls the superclass's default constructor. You can explicitly call a specific super constructor using the initializer list.

DARTRead-only
1
class Animal {
  String name;
  Animal(this.name);
}

class Dog extends Animal {
  String breed;

  Dog(String name, this.breed) : super(name);
}

void main() {
  var d = Dog('Rex', 'Labrador');
}

Common Mistakes

    • Forgetting to initialize non‑nullable fields: Ensure every field gets a value either directly, in the constructor, or in the initializer list.
    • Using this in initializer list before super call: You cannot reference this in the initializer list until after the super constructor has been called.
    • Overusing factory constructors: Only use them when you need to return an existing instance or perform logic before creation.
    • Not making constant constructors when possible: If a class is immutable, consider adding a const constructor to allow compile‑time constants.

Interview Questions

    • Q: What is the difference between a named constructor and a factory constructor? A: A named constructor always creates a new instance of the class, while a factory constructor can return an existing instance or a subtype.
    • Q: Can a class have both a default constructor and a named constructor? A: Yes, a class can have multiple constructors, including the default (if you don't define any) and named ones.
    • Q: When would you use a constant constructor? A: When the class represents an immutable value and you want objects that can be compile‑time constants (e.g., for performance or canonicalization).
    • Q: What is an initializer list used for? A: To initialize fields before the constructor body runs, assert conditions, or call a super constructor.

Key Takeaways

    • Constructors initialize objects. They have the same name as the class and no return type.
    • Dart supports default, parameterized, named, redirecting, constant, and factory constructors.
    • Use initializer lists to set fields or assert conditions before the constructor body.
    • Call superclass constructors using super() in the initializer list.
    • Factory constructors give you control over instance creation (caching, singletons, etc.).
    • Constant constructors (const) create compile‑time constants and must have all final fields.

Try it yourself

class User {
  String name;
  int age;
  
  User(this.name, this.age);
  
  User.guest() : this('Guest', 18);
  
  void introduce() {
    print('I am $name, $age years old');
  }
}

void main() {
  var u1 = User('Alice', 30);
  var u2 = User.guest();
  u1.introduce();
  u2.introduce();
}

Test Your Knowledge

Q1
of 4

Which keyword is used to define a factory constructor?

A
factory
B
static
C
new
D
create
Q2
of 4

What is the output of this code? class A { final int x; const A(this.x); } void main() { var a1 = const A(5); var a2 = const A(5); print(identical(a1, a2)); }

A
true
B
false
C
null
D
Error
Q3
of 4

How do you call a superclass constructor in Dart?

A
super() in the initializer list
B
super() in the constructor body
C
parent()
D
base()
Q4
of 4

Which constructor type can return an existing object instead of creating a new one?

A
Default
B
Named
C
Factory
D
Constant

Frequently Asked Questions

Can a constructor be private?

Yes, by using the underscore _ before the constructor name (e.g., _MyClass()). This is useful for implementing singletons or factory methods that control instance creation.

Do constructors support optional parameters?

Yes, constructors can have optional positional or named parameters, just like functions. For example: Person([this.name = 'Guest']) or Person({this.age = 18}).

Can a constructor be `async`?

No, constructors cannot be asynchronous. If you need to perform async work, consider a factory constructor that returns a Future or a separate static async method that creates an instance after async initialization.

What is the difference between `this()` and `super()` in a constructor?

this() calls another constructor in the same class; it's used for constructor redirection. super() calls a constructor of the superclass; it must be called in the initializer list before the constructor body.

Can a class have multiple constructors?

Yes, Dart classes can have multiple constructors – one default (or parameterized) and any number of named constructors. This provides flexibility in object creation.

What happens if I don't define any constructor?

Dart automatically provides a default constructor with no arguments. It simply calls the superclass's no‑argument constructor and does nothing else.

Can a constructor be `const` and `factory` at the same time?

No, a constructor cannot be both const and factory. const constructors must create new objects, while factory constructors may return existing ones.

How do I write a constructor that validates parameters before initializing fields?

You can use an initializer list with assert or run validation in the constructor body after the fields are initialized. For example: Person(this.name) : assert(name.isNotEmpty);

Previous

dart classes

Next

dart inheritance

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.