Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explanation of mixin "on" clause is inaccurate #3769

Open
munificent opened this issue Jan 20, 2022 · 0 comments
Open

Explanation of mixin "on" clause is inaccurate #3769

munificent opened this issue Jan 20, 2022 · 0 comments
Labels
a.language Relates to the Dart language tour d.enhancement Improves docs with specific ask e1-hours Can complete in < 8 hours of normal, not dedicated, work fix.examples Adds or changes example p2-medium Necessary but not urgent concern. Resolve when possible. st.triage.ltw Indicates Lead Tech Writer has triaged

Comments

@munificent
Copy link
Member

munificent commented Jan 20, 2022

Page URL

https://dart.dev/guides/language/language-tour#adding-features-to-a-class-mixins

Describe the problem

The language tour says:

Sometimes you might want to restrict the types that can use a mixin. For example, the mixin might depend on being able to invoke a method that the mixin doesn’t define. As the following example shows, you can restrict a mixin’s use by using the on keyword to specify the required superclass:

class Musician {
  // ...
}
mixin MusicalPerformer on Musician {
  // ...
}
class SingerDancer extends Musician with MusicalPerformer {
  // ...
}

In the preceding code, only classes that extend or implement the Musician class can use the mixin MusicalPerformer. Because SingerDancer extends Musician, SingerDancer can mix in MusicalPerformer.

This isn't a great motivating example for using an on clause. The code would be better written as:

class Musician {
  void dance() {
    print("dancin'");
  }
}

mixin MusicalPerformer implements Musician {
  void perform() {
    dance();
  }
  // ...
}

class SingerDancer extends Musician with MusicalPerformer {
  // ...
}

Note here that the MusicPerformer mixin declares that it implements Musician even though it doesn't actually provide an implementation of dance(). Even so, it is able to call dance() in its own body. That's the language ensures that when the mixin is applied to some class, the final resulting class does implement Musician and thus the call to dance() will always succeed.

This is better because an equally valid use of MusicalPerformer is:

class Musician {
  void dance() {
    print("dancin'");
  }
}

mixin MusicalPerformer implements Musician {
  void perform() {
    dance();
  }
  // ...
}

class SingerDancer with MusicalPerformer implements Musician {
  void dance() {
    print("sinin' and dancin'");
  }
}

Note here that SingerDancer does not extend Musician. It provides its own implementation of dance() and declares that it itself implements Musician. In other words, the implementation of dance() doesn't have to be above MusicalPerformer in the class hierarchy. Here, it's below, and that's fine too.

The on clause is only needed when a mixin contains a super call to some method, like:

mixin MusicalPerformer on Musician {
  void perform() {
    super.dance();
  }
}

Here, the on clause is necessary because it's not enough for the class applying the mixin to provide it's own definition of dance(). The dance() method has to be above the mixin on the class hierarchy or the super.dance() call will not be able to find it. The on clause ensures that any class applying the mixin must have some other class above the mixin that implements Musician.

on clauses are a weird, fairly rare feature. You only need them for super calls in the mixin. In most cases where a mixin just doing a regular method call on itself, an implements clause or defining the method as abstract in the mixin is what you want. You don't want to use on clauses for those simple cases because then you take flexibility away from classes applying the mixin.

Expected fix

I would explain using implements clauses and abstract method declarations in mixins to define what method calls the mixin's own methods are implemented in terms of. Then explain that if the mixin contains super calls, you can use an on clause to specify what methods it is allowed to call.

@parlough parlough added a.language Relates to the Dart language tour e1-hours Can complete in < 8 hours of normal, not dedicated, work d.enhancement Improves docs with specific ask fix.examples Adds or changes example p2-medium Necessary but not urgent concern. Resolve when possible. labels Jan 20, 2022
@atsansone atsansone added the st.triage.ltw Indicates Lead Tech Writer has triaged label Apr 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a.language Relates to the Dart language tour d.enhancement Improves docs with specific ask e1-hours Can complete in < 8 hours of normal, not dedicated, work fix.examples Adds or changes example p2-medium Necessary but not urgent concern. Resolve when possible. st.triage.ltw Indicates Lead Tech Writer has triaged
Projects
None yet
Development

No branches or pull requests

3 participants