Dart Mixin

Summary: in this tutorial, you’ll learn about Dart mixin and how to use mixins to reuse code in multiple hierarchies.

Introduction to the Dart mixins

Let’s start with an example.

First, define an abstract class called Model that is the base class of all model classes:

abstract class Model {
}Code language: Dart (dart)

Second, define three classes User, Post, and Comment that inherit from the Model class:

class User extends Model {}

class Post extends Model {}

class Comment extends Model {}Code language: Dart (dart)

Suppose you want to implement a shareable function for the Post and Comment classes but not for the User class. To do that, you’ll have a number of options.

1) Add the share() method to the Model class

In this option, we add the share() method to the Model class. Because the User class is a subclass of the Model class, it becomes shareable, which is not correct:

abstract class Model {
  void share(String content) {
    print('Share the $content');
  }
}Code language: Dart (dart)

Also, all the future classes that inherit from the Model class will be able to access the share() method which may not what you expected.

To work around this, you may override the share() method and raise an exception in the subclasses that you don’t want to be shareable. For example:

class User extends Model {
  @override
  void share(String content) {
    throw UnimplementedError();
  }
}Code language: Dart (dart)

However, this option is not ideal.

2) Creating a new base class for shareable classes

In this option, first, define a Shareable class that extends the Modelclass and add the share() method to the Shareable class:

abstract class ShareableModel extends Model {
  void share(String content) {
    print('Share the $content');
  }
}Code language: Dart (dart)

Second, extend the ShareableModel class from the Post and Comment classes:

class Post extends ShareableModel {}

class Comment extends ShareableModel {}Code language: Dart (dart)

This solution works fine for this class hierarchy.

However, if a class that is in another class hierarchy wants to reuse the share() method, it’s not possible.

3) Creating a new interface

In this option, first, define a Shareable interface and implement it from the Post and Comment classes:

abstract class Shareable {
  void share(String $content);
}

class Post extends Model implements Shareable {
  void share(String content) {
    print('Share the $content');
  }
}

class Comment extends Model implements Shareable {
  void share(String content) {
    print('Share the $content');
  }
}Code language: Dart (dart)

However, this option causes duplicate code in the Post and Comment class.

Dart mixin to the rescue

All the three options have pros and cons and none of them is ideal. To resolve this, Dart comes up with the mixin concept.

Mixins allow you to share behaviors between one or more classes without using inheritance.

A mixin is like a class. To define a mixin, you use the mixin keyword instead of the class keyword. Inside the mixin, you define the methods.

For example, the following defines the Shareable mixin:

mixin Shareable {
  void share(String content) {
    print('Share the $content');
  }
}Code language: Dart (dart)

Unlike a class, a mixin doesn’t have a constructor and it cannot be instantiated. For example, the following causes an error because it attempts to create an object from a mixin:

var share = Shareable(); // ERRORCode language: Dart (dart)

Also, you cannot inherit from a mixin. For example, the following attempts to extend a mixin. It results in an error:

// ERROR
class MyShareable extends Shareable {}Code language: Dart (dart)

To use a mixin in other classes, you use the with keyword.

For example, the following Post and Comment classes extend the Model class and use the Shareable mixin:

class Post extends Model with Shareable {}

class Comment extends Model with Shareable {}Code language: Dart (dart)

Once a class uses a mixin, its objects can access all the methods of the mixin. For example:

var post = Post();
post.share('The first post.');

var comment = Comment();
comment.share('My first comment.');Code language: Dart (dart)

If you want to use the Shareable mixin in a class, you use the with keyword. For example, the following defines the Video class that is not in the current class hierarchy and uses the Shareable mixin:

class Video with Shareable {}Code language: Dart (dart)

Put it all together.

abstract class Model {}

class User extends Model {}

mixin Shareable {
  void share(String content) {
    print('Share the $content');
  }
}

class Post extends Model with Shareable {}

class Comment extends Model with Shareable {}

class Video with Shareable {}

void main() {
  var post = Post();
  post.share('The first post.');

  var comment = Comment();
  comment.share('My first comment.');

  var video = Video();
  video.share('Share the video');
}Code language: Dart (dart)

Summary

  • Use mixins to share behaviors between one or more classes.
  • Use the mixin keyword to define a mixin. Unlike a class, a mixin cannot be instantiated and it cannot have a constructor.
  • Use the with keyword to use a mixin in a class.
Was this tutorial helpful ?