Class modifiers

Vinit MepaniVinit Mepani
3 min read

Dart adds a few new modifiers that you can place on class and mixin declarations. If you are the author of a library package, these modifiers give you more control over what users are allowed to do with the types that your package exports. This can make it easier to evolve your package, and easier to know if a change to your code may break users.

Dart 3.0 also includes a breaking change around using classes as mixins. This change might not break your class, but it could break users of your class.

This guide walks you through these changes so you know how to use the new modifiers, and how they affect users of your libraries.

The mixin modifier on classes

The most important modifier to be aware of is mixin. Language versions prior to Dart allow any class to be used as a mixin in another class’s with clause, UNLESS the class:

  • Declares any non-factory constructors.

  • Extends any class other than Object.

This makes it easy to accidentally break someone else’s code, by adding a constructor or extends clause to a class without realizing that others are using it in a with clause.

Dart 3.0 no longer allows classes to be used as mixins by default. Instead, you must explicitly opt-in to that behavior by declaring a mixin class:

mixin class Both {}

class UseAsMixin with Both {}
class UseAsSuperclass extends Both {}

If you update your package to Dart and don’t change any of your code, you may not see any errors. But you may inadvertently break users of your package if they were using your classes as mixins.

Migrating classes as mixins

If the class has a non-factory constructor, an extends clause, or a with clause, then it already can’t be used as a mixin. Behavior won’t change with Dart 3.0; there’s nothing to worry about and nothing you need to do.

In practice, this describes about 90% of existing classes. For the remaining classes that can be used as mixins, you have to decide what you want to support.

Here are a few questions to help decide. The first is pragmatic:

  • Do you want to risk breaking any users? If the answer is a hard “no”, then place mixin before any and all classes that could be used as a mixin. This exactly preserves the existing behavior of your API.

On the other hand, if you want to take this opportunity to rethink the affordances your API offers, then you may want to not turn it into a mixin class. Consider these two design questions:

  • Do you want users to be able to construct instances of it directly? In other words, is the class deliberately not abstract?

  • Do you want people to be able to use the declaration as a mixin? In other words, do you want them to be able to use it in with clauses?

If the answer to both is “yes”, then make it a mixin class. If the answer to the second is “no”, then just leave it as a class. If the answer to the first is “no” and the second is “yes”, then change it from a class to a mixin declaration.

The last two options, leaving it a class or turning it into a pure mixin, are breaking API changes. You’ll want to bump the major version of your package if you do this.

0
Subscribe to my newsletter

Read articles from Vinit Mepani directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vinit Mepani
Vinit Mepani

"Hello World, I'm Vinit Mepani, a coding virtuoso driven by passion, fueled by curiosity, and always poised to conquer challenges. Picture me as a digital explorer, navigating through the vast realms of code, forever in pursuit of innovation. In the enchanting kingdom of algorithms and syntax, I wield my keyboard as a magical wand, casting spells of logic and crafting solutions to digital enigmas. With each line of code, I embark on an odyssey of learning, embracing the ever-evolving landscape of technology. Eager to decode the secrets of the programming universe, I see challenges not as obstacles but as thrilling quests, opportunities to push boundaries and uncover new dimensions in the realm of possibilities. In this symphony of zeros and ones, I am Vinit Mepani, a coder by passion, an adventurer in the digital wilderness, and a seeker of knowledge in the enchanting world of code. Join me on this quest, and let's create digital wonders together!"