ZetCode

Dart object

last modified January 18, 2021

Dart object tutorial shows how to work with objects in Dart language. An object is a basic building block of a Dart program.

Object

Objects are basic building blocks of a Dart program. An object is a combination of data and methods. The data and the methods are called members of an object. Objects communicate together through methods. Each object can receive messages, send messages and process data.

There are two steps in creating an object. First, we define a class. A class is a template for an object. It is a blueprint which describes the state and behavior that the objects of the class all share. A class can be used to create many objects. Objects created at runtime from a class are called instances of that particular class. A new instance is created with the new keyword; since Dart 2.0, the keyword is optional.

Objects have members consisting of functions and data. We use a dot (.) operator to refer to an instance variables or methods.

Object-oriented programming (OOP) is a programming paradigm that uses objects and their interactions to design applications and computer programs.

Dart objects

In Dart, we work with objects. Even numbers or string literals are objects.

objects.dart
class Being {}

void main() {
  var b = Being();

  print(b.hashCode);
  print("falcon".toUpperCase());
  print(2.isNegative);

  print(b.runtimeType);
  print(2.runtimeType);
}

In the example, we work with various objects.

class Being {}

With the class keyword, we define a template for an object. In our case, the definition is empty.

var b = Being();

We create a new instance of a Being. The new keyword is optional.

print(b.hashCode);

Even though the object is empty, it has some built-in methods and attributes. This is because all created objects implicitly inherit from the mother of all objects: the Object.

print("falcon".toUpperCase());

The "falcon" is a string literal, which is an object itself. (This is not true for many other computer languages.) We call the object's toUpperCase method.

print(2.isNegative);

Even number literals are objects.

print(b.runtimeType);
print(2.runtimeType);

Here we check the runtime types of two objects.

$  dart objects.dart
511903303
FALCON
false
Being
int

Dart object attributes

Object attributes is the data bundled in an instance of a class. The object attributes are called instance variables or member fields. An instance variable is a variable defined in a class, for which each object in the class has a separate copy.

All instance variables generate an implicit getter method. Non-final instance variables also generate an implicit setter method.

attributes.dart
class Person {
  var name;
  var occupation;
}

void main() {
  var p1 = Person();
  p1.name = "John Doe";
  p1.occupation = "gardener";

  var p2 = Person();
  p2.name = "Roger Roe";
  p2.occupation = "driver";

  print("${p1.name} is a ${p1.occupation}");
  print("${p2.name} is a ${p2.occupation}");
}

We have a class with two member fields: name and occupation.

var p1 = Person();
p1.name = "John Doe";
p1.occupation = "gardener";

We create a new Person object and set the two attributes.

var p2 = Person();
p2.name = "Roger Roe";
p2.occupation = "driver";

A completely new object with its unique attributes is created.

print("${p1.name} is a ${p1.occupation}");
print("${p2.name} is a ${p2.occupation}");

We output the attributes of the two objects.

$ dart attributes.dart 
John Doe is a gardener
Roger Roe is a driver

Dart object methods

Methods are functions defined inside the body of a class. They are used to perform operations with the attributes of our objects. Methods bring modularity to our programs.

methods.dart
import 'dart:math';

class Circle {
  int radius;

  double area() {
    return this.radius * this.radius * pi;
  }
}

void main() {
  var c = Circle();
  c.radius = 5;

  print(c.area());
}

In the code example, we have a Circle class. Its area method computes the area of a circle.

double area() {
  return this.radius * this.radius * pi;
}

The area method returns the area of a circle. The pi is a constant form the dart:math library.

var c = Circle();
c.radius = 5;

A new circle is created. We set its radius attribute.

print(c.area());

We call the area method of the circle object through the dot operator.

$ dart methods.dart 
78.53981633974483

Dart object constructor

A constructor is a special kind of a method. It is automatically called when the object is created. Constructors do not return values. The purpose of the constructor is to initiate the state of an object. Constructors have the same name as the class.

constructor.dart
class User {
  String name;
  String occupation;

  User(String name, String occupation) {
    this.name = name;
    this.occupation = occupation;
  }
}

void main() {
  var u1 = new User("John Doe", "gardener");
  var u2 = new User("Roder Roe", "driver");

  print("${u1.name} is a ${u1.occupation}");
  print("${u2.name} is a ${u2.occupation}");
}

We have a User class. Its constructor initiates two attributes: name and occupation.

User(String name, String occupation) {
  this.name = name;
  this.occupation = occupation;
}

If the names of the object attributes and constructor arguments are the same, we refer to the object attributes with the this keyword.

var u1 = new User("John Doe", "gardener");

When we create a new User object, we pass the constructor two values.

$ dart constructor.dart 
John Doe is a gardener
Roder Roe is a driver

Dart toString method

Each object has a toString method inherited from the Object superclass. It returns a human-readable representation of an object. Note that when we call the print method with an object as a parameter, the toString is being called.

tostring.dart
class User {
  String name;
  String occupation;

  User(this.name, this.occupation);

  String toString() {
    return "$name is a $occupation";
  }
}

void main() {
  var u1 = new User("John Doe", "gardener");
  var u2 = new User("Roder Roe", "driver");

  print(u1);
  print(u2);
}

We have the User class in which we override the default implementation of the toString method.

String toString() {
  return "$name is a $occupation";
}

The toString method tells the name of the user and his occupation.

print(u1);
print(u2);

The toString is called for both objects; we do not need to call the method explicitly.

Dart automatic initializers

Dart has syntax for automatic initialization of attributes in the constructor.

automatic_initializers.dart
class User {
  String name;
  String occupation;

  User(this.name, this.occupation);
}

void main() {
  var u1 = new User("John Doe", "gardener");
  var u2 = new User("Roder Roe", "driver");

  print("${u1.name} is a ${u1.occupation}");
  print("${u2.name} is a ${u2.occupation}");
}

We pass this.name and this.occupation to the constructor. We don't need to specify the data types; they are inferred.

Dart named parameters

With {}, we can create named parameters. When passing a value to the constructor, we need to prefix it with the name of the parameter.

named_parameters.dart
class User {
  String name;
  String occupation;

  User({this.name, this.occupation});

  String toString() {
    return "$name is a $occupation";
  }
}

void main() {
  var u1 = new User(name: "John Doe", occupation: "gardener");
  print(u1);
}

We have an example with named parameters.

Dart object inheritance

The inheritance is a way to form new classes using classes that have already been defined. The newly formed classes are called derived classes, the classes that we derive from are called base classes. The derived classes (descendants) override or extend the functionality of the base classes (ancestors).

We use the extends keyword to inherit from a parent class.

inheritance.dart
class Being {
  static int count = 0;

  Being() {
    count++;
    print("Being is created");
  }

  void getCount() {
    print("There are $count Beings\n");
  }
}

class Human extends Being {
  Human() {
    print("Human is created");
  }
}

class Animal extends Being {
  Animal() {
    print("Animal is created");
  }
}

class Dog extends Animal {
  Dog() {
    print("Dog is created");
  }
}

void main() {
  Human();
  var dog = Dog();
  dog.getCount();
}

The Human and the Animal classes inherit from the Being class. The Dog class inherits directly from the Animal class and indirectly from the Being class. We also introduce a concept of a static variable.

static int count = 0;

We define a static variable. Static members are members that are shared by all instances of a class.

Being() {
  count++;
  print("Being is created");
}

Each time the Being class is instantiated, we increase the count variable by one. This way we keep track of the number of instances created.

class Animal extends Being {
...
class Dog extends Animal {
...

The Animal inherits from the Being and the Dog inherits from the Animal. Indirectly, the Dog inherits from the Being as well.

Human();
var dog = Dog();
dog.getCount();

We create instances from the Human and from the Dog classes. We call the getCount method of the Dog object.

$ dart inheritance.dart 
Being is created
Human is created
Being is created
Animal is created
Dog is created
There are 2 Beings

Dart check type

In Dart, we can check the type with the is keyword.

check_type.dart
class Person {}

class Student {}

void main() {
  var p = Person();
  var s = Student();

  print(p is Person);
  print(s is Person);
  print(p is Object);
  print(s is Object);

  print(2 is int);
  print(2 is Object);
}

In the example, we check the types of several objects.

print(p is Person);

We check if p is of type Person, which is true.

print(s is Person);

We check if s is of type Person, which is not true.

print(2 is Object);

Since all objects implicitly inherit from Object, this line prints true.

$ dart check_type.dart 
true
false
true
true
true
true

In this tutorial, we have covered objects in Dart.

List all Dart tutorials.