Dart Constructors

Special methods for creating and initializing objects

🔧 What are Dart Constructors?

Constructors are special methods that create and initialize objects when they are instantiated. They set up initial values and prepare objects for use in your program.


// Simple constructor example
class Car {
  String brand;
  int year;
  
  Car(this.brand, this.year); // Constructor
}

Car myCar = Car('Toyota', 2023);
                                    

Types of Constructors

🔨

Default Constructor

Simple constructor with no parameters

class Person {
  String name = 'Unknown';
  
  Person(); // Default constructor
}
⚙️

Parameterized

Constructor that accepts parameters

class Student {
  String name;
  int age;
  
  Student(this.name, this.age);
}
🏷️

Named Constructor

Constructor with a specific name

class Point {
  double x, y;
  
  Point.origin() {
    x = 0;
    y = 0;
  }
}
🔄

Factory Constructor

Constructor that can return instances

class Logger {
  static Logger _instance;
  
  factory Logger() {
    return _instance ??= Logger._();
  }
}

🔹 Default Constructor

The simplest type of constructor:

class Animal {
  String name;
  String species;
  
  // Default constructor
  Animal() {
    name = 'Unknown';
    species = 'Unknown';
    print('Animal created with default values');
  }
  
  void displayInfo() {
    print('Name: $name, Species: $species');
  }
}

void main() {
  Animal animal1 = Animal();
  animal1.displayInfo();
  
  // Modify properties after creation
  animal1.name = 'Fluffy';
  animal1.species = 'Cat';
  animal1.displayInfo();
}

Output:

Animal created with default values

Name: Unknown, Species: Unknown

Name: Fluffy, Species: Cat

🔹 Parameterized Constructor

Constructor that accepts parameters to initialize objects:

class Rectangle {
  double width;
  double height;
  
  // Parameterized constructor
  Rectangle(this.width, this.height) {
    print('Rectangle created: ${width}x$height');
  }
  
  // Alternative way to write constructor
  // Rectangle(double w, double h) {
  //   width = w;
  //   height = h;
  // }
  
  double getArea() {
    return width * height;
  }
  
  double getPerimeter() {
    return 2 * (width + height);
  }
  
  void displayInfo() {
    print('Width: $width, Height: $height');
    print('Area: ${getArea()}');
    print('Perimeter: ${getPerimeter()}');
  }
}

void main() {
  Rectangle rect1 = Rectangle(5.0, 3.0);
  Rectangle rect2 = Rectangle(10.0, 7.5);
  
  print('Rectangle 1:');
  rect1.displayInfo();
  
  print('\nRectangle 2:');
  rect2.displayInfo();
}

Output:

Rectangle created: 5.0x3.0

Rectangle created: 10.0x7.5

Rectangle 1:

Width: 5.0, Height: 3.0

Area: 15.0

Perimeter: 16.0

Rectangle 2:

Width: 10.0, Height: 7.5

Area: 75.0

Perimeter: 35.0

🔹 Named Constructors

Create multiple constructors with different names:

class Employee {
  String name;
  String department;
  double salary;
  
  // Default constructor
  Employee(this.name, this.department, this.salary);
  
  // Named constructor for interns
  Employee.intern(this.name, this.department) {
    salary = 1000.0;
    print('$name joined as intern in $department');
  }
  
  // Named constructor for managers
  Employee.manager(this.name, this.department) {
    salary = 8000.0;
    print('$name joined as manager in $department');
  }
  
  // Named constructor for senior employees
  Employee.senior(this.name, this.department, double experience) {
    salary = 5000.0 + (experience * 500);
    print('$name joined as senior with $experience years experience');
  }
  
  void displayInfo() {
    print('Name: $name');
    print('Department: $department');
    print('Salary: \$${salary.toStringAsFixed(2)}');
    print('---');
  }
}

void main() {
  Employee emp1 = Employee('John', 'IT', 4500.0);
  Employee emp2 = Employee.intern('Alice', 'Marketing');
  Employee emp3 = Employee.manager('Bob', 'Sales');
  Employee emp4 = Employee.senior('Carol', 'Engineering', 5.0);
  
  emp1.displayInfo();
  emp2.displayInfo();
  emp3.displayInfo();
  emp4.displayInfo();
}

Output:

Alice joined as intern in Marketing

Bob joined as manager in Sales

Carol joined as senior with 5.0 years experience

Name: John

Department: IT

Salary: $4500.00

---

Name: Alice

Department: Marketing

Salary: $1000.00

---

🔹 Constructor with Optional Parameters

Use optional parameters to make constructors more flexible:

class Product {
  String name;
  double price;
  String category;
  bool inStock;
  
  // Constructor with optional parameters
  Product(this.name, this.price, {this.category = 'General', this.inStock = true}) {
    print('Product "$name" created in $category category');
  }
  
  void displayProduct() {
    print('Product: $name');
    print('Price: \$${price.toStringAsFixed(2)}');
    print('Category: $category');
    print('In Stock: ${inStock ? 'Yes' : 'No'}');
    print('---');
  }
}

void main() {
  // Using constructor with different parameter combinations
  Product product1 = Product('Laptop', 999.99);
  Product product2 = Product('Phone', 599.99, category: 'Electronics');
  Product product3 = Product('Book', 29.99, category: 'Education', inStock: false);
  
  product1.displayProduct();
  product2.displayProduct();
  product3.displayProduct();
}

Output:

Product "Laptop" created in General category

Product "Phone" created in Electronics category

Product "Book" created in Education category

Product: Laptop

Price: $999.99

Category: General

In Stock: Yes

---

🧠 Test Your Knowledge

What is the syntax for a named constructor in Dart?