In this tutorial, I will show you how to define and work with Constructors in Dart/Flutter. There are many types of Constructors that you will need to know when working with Dart class.
Related Posts:
– Dart/Flutter String Methods & Operators tutorial with examples
– Dart/Flutter Future Tutorial with Examples
– Dart/Flutter List Tutorial with Examples
– Dart/Flutter Map Tutorial with Examples
– Dart/Flutter – Sort list of Objects
Contents
Dart Constructor methods
Constructor is a special method of Dart class which is automatically called when the object is created. The constructor is like a function with/without parameter but it doesn’t have a return type.
For example, this is Customer
class with constructor that has the same name:
class Customer {
String name;
int age;
String location;
// constructor
Customer(String name, int age, String location) {
this.name = name;
this.age = age;
this.location = location;
}
}
Now you can create new object using a constructor.
var customer = Customer("bezkoder", 26, "US");
If we don’t define any constructor, the default constructor below will be created.
Customer() {
}
Dart Constructor with Syntactic sugar
If you use constructor with nornal syntax above, you need to write boilerplate to assign each argument to an instance variable.
Dart supports syntactic sugar to make it easy.
class Customer {
String name;
int age;
String location;
Customer(this.name, this.age, this.location);
}
Multiple constructors in Dart/Flutter
How about the case you want to have more than one constructor. For example, there are 2 constructors you desire to use:
Customer(String name, int age, String location) {
this.name = name;
this.age = age;
this.location = location;
}
Customer(this.name, this.age) {
this.name = name;
this.age = age;
}
But if you define both of them in a class, there will be a compiler error.
Dart provides Named constructor that helps you implement multiple constructors with more clarity:
class Customer {
// ...
Customer(String name, int age, String location) {
this.name = name;
this.age = age;
this.location = location;
}
// Named constructor - for multiple constructors
Customer.withoutLocation(this.name, this.age) {
this.name = name;
this.age = age;
}
Customer.empty() {
name = "";
age = 0;
location = "";
}
@override
String toString() {
return "Customer [name=${this.name},age=${this.age},location=${this.location}]";
}
}
You can write it more simply with Syntactic sugar:
Customer(this.name, this.age, this.location);
Customer.withoutLocation(this.name, this.age);
Customer.empty() {
name = "";
age = 0;
location = "";
}
Now we can create new Customer
object by these methods.
var customer = Customer("bezkoder", 26, "US");
print(customer);
// Customer [name=bezkoder,age=26,location=US]
var customer1 = Customer.withoutLocation("zkoder", 26);
print(customer1);
// Customer [name=zkoder,age=26,location=null]
var customer2 = Customer.empty();
print(customer2);
// Customer [name=,age=0,location=]
So, is there any way to make Customer.empty()
neat?
And how to initialize an empty value for location field when calling Customer.withoutLocation()
instead of null
?
Yes, we can.
Let’s take a look at Redirecting Constructor.
Redirecting Constructor
We can redirect a constructor to another constructor in the same class by using a colon (:). Remember that body of Redirecting Constructor is empty.
For example, I will rewrite Customer.empty()
& Customer.withoutLocation()
above.
class Customer {
String name;
int age;
String location;
Customer(this.name, this.age, this.location);
// Redirecting constructors
Customer.empty() : this("", 0, "");
Customer.withoutLocation(String name, int age) : this(name, age, "");
Let’s run and check again:
var customer1 = Customer.empty();
print(customer1);
// Customer [name=,age=0,location=]
var customer2 = Customer.withoutLocation("zkoder", 26);
print(customer2);
// Customer [name=zkoder,age=26,location=]
Factory Constructor in Dart/Flutter
We can use the factory
keyword for a constructor that return an object instead of creating a new instance.
class Customer {
String name;
int age;
String location;
static final Customer origin = Customer("", 0, "");
// factory constructor
factory Customer.create() {
return origin;
}
@override
String toString() { ... }
}
var customer = Customer.create();
print(customer);
// Customer [name=,age=0,location=]
Dart/Flutter Constructor with Optional parameters
We can define constructor with two types of parameters: required and optional. The required parameters (which we used in sections above) are listed first, followed by any optional parameters.
Optional parameters can be Named or Positional.
Dart Constructor using Square brackets: Positional optional parameters
You can wrap one or more parameters in square brackets [ ]
to make them as optional positional parameters.
class Customer {
String name;
int age;
String location;
// Positional optional parameters
Customer(this.name, [this.age, this.location]);
@override
String toString() {
return "Customer [name=${this.name},age=${this.age},location=${this.location}]";
}
}
Let’s make some test by calling constructor without the optional parameters:
var customer = Customer("bezkoder", 26, "US");
print(customer);
// Customer [name=bezkoder,age=26,location=US]
var customer1 = Customer("bezkoder", 26);
print(customer1);
// Customer [name=bezkoder,age=26,location=null]
var customer2 = Customer("zkoder");
print(customer2);
// Customer [name=zkoder,age=null,location=null]
Dart Constructor using Curly braces: Named optional parameters
We can also definie a constructor using curly braces { }
to specify named parameters.
class Customer {
String name;
int age;
String location;
// Named optional parameters
Customer(this.name, {this.age, this.location});
@override
String toString() {
return "Customer [name=${this.name},age=${this.age},location=${this.location}]";
}
}
When calling the constructor, we have to use parameter name to assign a value which separated with colan paramName: value
.
var customer = Customer("bezkoder", location: "US", age: 26);
print(customer);
// Customer [name=bezkoder,age=26,location=US]
var customer1 = Customer("bezkoder", age: 26);
print(customer1);
// Customer [name=bezkoder,age=26,location=null]
var customer2 = Customer("zkoder");
print(customer2);
// Customer [name=zkoder,age=null,location=null]
You can see that the order of parameters does not matter. It can avoid confusion while passing value for the constructor which has many parameter.
Dart/Flutter Constructor default value
For the constructors with either Named or Positional parameters, we can use =
to define default values.
The default values must be compile-time constants. If we don’t provide value, the default value is null.
Positional optional parameters
class Customer {
String name;
int age;
String location;
Customer(this.name, [this.age, this.location = "US"]);
@override
String toString() {
return "Customer [name=${this.name},age=${this.age},location=${this.location}]";
}
}
Now create some Customer
objects, you can see that default value for age
is null
and for location
is "US"
.
var customer = Customer("bezkoder", 26, "US");
print(customer);
// Customer [name=bezkoder,age=26,location=US]
var customer1 = Customer("bezkoder", 26);
print(customer1);
// Customer [name=bezkoder,age=26,location=US]
var customer2 = Customer("zkoder");
print(customer2);
// Customer [name=zkoder,age=null,location=US]
Named optional parameters
class Customer {
String name;
int age;
String location;
Customer(this.name, {this.age, this.location = "US"});
@override
String toString() {
return "Customer [name=${this.name},age=${this.age},location=${this.location}]";
}
}
Let’s run to check default values for age
& location
.
var customer = Customer("bezkoder", age: 26, location: "US");
print(customer);
// Customer [name=bezkoder,age=26,location=US]
var customer1 = Customer("bezkoder", age: 26);
print(customer1);
// Customer [name=bezkoder,age=26,location=US]
var customer2 = Customer("zkoder");
print(customer2);
// Customer [name=zkoder,age=null,location=US]
Constant constructor
If we want all intances of our class will never change, we can define a const constructor in which all fields are final
.
class ImmutableCustomer {
final String name;
final int age;
final String location;
// Constant constructor
const ImmutableCustomer(this.name, this.age, this.location);
}
Now we can put the const
keyword before the constructor name:
var immutableCustomer = const ImmutableCustomer("zkoder", 26, "US");
// immutableCustomer.name = ... // compile error
Conclusion
Today we’ve learned many types of Constructors in Dart/Flutter, from normal syntax to syntactic sugar, from single constructor to multiple constructors using Dart Named constructor, from Redirecting to factory constructor, from required parameters to optional parameters. You also look at how to define a const constructor in a class.
Happy Learning! See you again.
Further Reading
– Dart/Flutter String Methods & Operators tutorial with examples
– Dart/Flutter Future Tutorial with Examples
– Dart/Flutter List Tutorial with Examples
– Dart/Flutter Map Tutorial with Examples
– Dart/Flutter – Sort list of Objects
Wonderful well written tutorial
nice work, do update the code by making the variables nullable.
Simple but very accurate tutorial. Thanks for sharing this one. A must read tutorial!
Great Dart tutorial, keep it up!
Pretty! This has been an extremely wonderful tutorial. Thank you!
Thank you sir! Respect <3
Great stuff! Would be nice to update to nullsafety…
I want to say that this Dart tutorial is well-written and comprehensive. I’d like to see far more tutorials like this!
Thanks
thank you bezkoder for this tutorial!
I can definitely see your expertise within the tutorial you write. Thanks!
Great stuff! Would be nice to update to nullsafety…
This is very helpful, thank you!
Very nice and so easy thanks 😀
Awesome thanks heaps for a excellent write up
Very cool web site!! Excellent.. Amazing..
Thanks for the tutorial!
WOᎳ just teh tutorial what I was looking for. Thanks!
I love reading your tutorial.
You have a great blog with many useful tutorials. Many thanks!
Thank you. Very helpful!
thanks for this text, it cleared a lot of my doubts