The constructor is to create and initialize an objects of classes.
OR
A constructor is used in instance creation to obtain objects of classes.
A constructor name always begins with the name of its class.
The following code snippet shows how to define a constructor with parameters and initialize an objects of class.
class Person {
// Person Constructor with parameter.
Person(String name) {}
}
main() {
var person = Person('Rock'); //
}
The default constructor has no arguments and no name.
If no constructor is specified for a class, it implicitly has a default constructor, that is used in instance creation.
()
operator use to define the constructor for instance creation.
The following code snippet show the default construct of a class.
class Person {}
main() {
var person = Person();
}
The initializer list is to invoke superclass constructor, and also initialize variables before the constructor body runs.
Initializer lists are handy when setting up final fields.
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin);
}
The right-hand side of an initializer does not have access to this
keyword.
In the case you don't want to expose your variables defined in Point and your mark those as private, the initializer would be a good option.
The redirecting constructor is to only redirect to invoke another constructor in the same class.
A redirecting constructor has no body; instead, it has a redirect clause that specifies which constructor the invocation is redirected to, and with which arguments. The constructor call appearing after a colon (:).
The following code snippet shows how th redirect constructor, which invokes default constructor.
class Skill {
String name;
String level;
Skill(this.name, this.level);
Skill.onlySkill(String name) : this(name, '');
}
main() {
var skill = Skill.onlySkill('Angular');
print(skill.name); // Angular
}
The factory constructor is that doesn’t always create a new instance of its class.
A factory constructor can produce instances that are not freshly allocated:
Factories can return instances of different classes
It have several advantages over direct object instantiation, such as:
Factory constructor either unnamed or named.
To create a factory constructor, use the factory
keyword.
class Logger {
// instance variables or properties
final String name;
bool mute = false;
// class variable or property
static final Map<String, Logger> _cache = <String, Logger>{};
// Declare unnamed factory constructor using factory keyword
factory Logger(String name) {
return _cache.putIfAbsent(name, () => Logger._internal(name));
}
// Named generative private constructor
Logger._internal(this.name);
// instance method
void log(String msg) {
if (!mute) print(msg);
}
}
main() {
var logger = Logger('Update failed');
logger.log('Update failed, please try later');
}
The following example, shows the factory constructor returns the instance of a subclass Employee
.
class Person {
String name;
bool isEmployee;
Person(this.name, this.isEmployee);
// named factory
factory Person.employeeOnly(String name) {
return Employee(name);
}
}
class Employee extends Person {
Employee(String name) : super(name, true);
}
main() {
var person = Person.employeeOnly('Rock star');
print(person.isEmployee);
}
The constant constructor is to make class objects compile time constants.
If your class produces objects that never change, you can make these objects compile-time constants.
Put the const
reserved keyword before the constructor name.
const
reserved keyword before the constructor name while defining a constant constructor.final
.The following code snippet shows how to define constant constructor.
class Person {
// Make all instance variable are final
final String firstName;
final String lastName;
// All final variables must be initialized,
// Define const constructor using const keyword
const Person(this.firstName, this.lastName);
}
main() {
var person = Person('Rock', 'Star');
print(person.firstName);
print(person.lastName);
}
Note: Instance variables 'firstName', 'lastName' can't be used as a setter because it is final.
main() {
var person = Person('Rock', 'Star');
// 'firstName' can't be used as a setter because it is final.
person.firstName = "Oorja"; //Error
}
Note: Constant constructors don’t always create constants.
The this
keyword is to refer to the current instance.
Use this
keyword to assigning a constructor argument to an instance variable.
Use this.propertyName
when declaring the constructor:
class Employee {
String firstName;
String lastName;
Employee(this.firstName, this.lastName);
}
main() {
var employee = Employee('Rock', 'Star');
}
The following snippet shows how to use this keyword is named parameters.
this keyword works for named parameters, too. Property names become the names of the parameters:
class Employee {
String firstName;
String lastName;
// Name parameters
Employee({this.firstName, this.lastName});
}
main() {
var employee = Employee(firstName: 'Rock', lastName: 'Star');
}
The following code snippet shows how to use this keyword with positional parameters.
You can also use this with constructors positional parameters.
class Employee {
String firstName;
String lastName;
// Positional parameters
Employee([this.firstName, this.lastName]);
}
main() {
var employee = Employee('Rock', 'Star');
}
The following code snippet shows how this keyword used with named and positional parameters wit default values.
For optional parameters, default values work as expected:
// Positional parameters
Employee([this.firstName = '', this.lastName = '']);
// or
// Named parameters
Employee({this.firstName = '', this.lastName = ''});
The named constructor is to create multiple constructors for a class.
The class can have only one unnamed constructor, but it can have any number of named constructors to allow classes to have multiple constructors.
The following code snippet shows hot to use a named constructor to implement multiple constructors for a class or to provide extra clarity.
class Employee {
String firstName;
String lastName;
Employee(this.firstName, this.lastName);
// Named Constructor
Employee.fromEmployee(Employee employee) {
firstName = employee.firstName;
lastName = employee.lastName;
}
}
Named constructors can also be private by starting the name with _
The following code snippet shows how to create private constructor, which accessible only from inside the class itself.
Employee._(this.firstName, this.lastName);
// private named constructor
Employee._fromEmployee(Employee employee) {
firstName = employee.firstName;
lastName = employee.lastName;
}
The NoSuchMethod
is to invoke when a non-existing method or property is accessed.
Invoked when a non-existent method or property is accessed.
The noSuchMethod()
is invoked implicitly during execution in situations whenever code attempts to use a non-existent method or instance variable.
You can override noSuchMethod in your class to provide custom behavior.
Accessing non-existent member results in a NoSuchMethodError. The default behavior is to throw a NoSuchMethodError
.
class Person {}
main() {
dynamic person = Person();
person.fullName(); // NoSuchMethodError: Class 'Person' has no instance method 'fullName'.
}Override `noSuchMethod()` to avoid error and provide custom behavior.
```dart
class Person {
noSuchMethod(Invocation invocation) {
print('You tried to access a non-existent member: ' +
'${invocation.memberName}');
}
}
main() {
dynamic person = Person();
person
.fullName(); // You tried to access a non-existent member: Symbol("fullName")
}
The Overriding members
is to override default behavior or state, to provide specific behavior or state.
Subclasses can override instance methods, getters, and setters. You can use the @override
annotation to indicate that you are intentionally overriding a member.
class Customer {
double Discount() {
return 2.5;
}
}
class RetailCustomer extends Customer {
double Discount() {
return 5.0;
}
}
class WholeSaleCustomer extends Customer {
double Discount() {
return 7.5;
}
}
main() {
var retailCustomer = RetailCustomer();
print('The discount for retail customers ${retailCustomer.Discount()} %');
var wholeSaleCustomer = WholeSaleCustomer();
print(
'The discount for whole sate customers ${wholeSaleCustomer.Discount()} %');
}
The Overriding operator
is to provide the custom implementation of an operation in case one or both of the operands are of that type.
You can override the operators.
Operators are instance methods with special names. An operator declaration is identified using the built-in identifier operator.
The following example,shows of a class that overrides the + and - operators
class Vector {
final int x, y;
Vector(this.x, this.y);
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}