mixin Foo on Bar {}
class Bang with Foo{}
class Bar extends Bang {
Bar() {
print('Bar');
}
}
mixin Foo on Bar {}
class Bar with Foo {
Bar() {
print('Bar');
}
}
This works:mixin Foo on Bar {}
class Bang with Foo{}
class Bar extends Bang {
Bar() {
print('Bar');
}
}But this:mixin Foo on Bar {}
class Bar with Foo {
Bar() {
print('Bar');
}
}Produces:scratch_1.dart:2:7: Error: 'Foo' is a supertype of itself.mixin Foo on Bar {}^scratch_1.dart:4:7: Error: 'Object with Foo' is a supertype of itself.class Bar with Foo {^scratch_1.dart:4:7: Error: 'Bar' is a supertype of itself.class Bar with Foo {^
mixin Foo on Baz {void foo() => super.baz();}class Baz {void baz() { print('Baz.baz'); }}abstract class Baz2 implements Baz {}class Bar extends Baz2 with Foo {void baz() { print('Bar.baz'); }Bar() {print('Bar');}}main() {Bar().foo(); // Throws, because `Bar.baz` isn't a super-method as seen from `Foo`.}
Oddly, Google (which makes Dart!) returns no results for the phrase “is a supertype of itself”.
--
For more ways to connect visit https://dart.dev/community
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
To view this discussion on the web visit https://groups.google.com/a/dartlang.org/d/msgid/misc/61C9B215-E514-4B76-9DC2-472387B1C63F%40gmail.com.
and then mix that mixin back into the class, how do I proceed?The reason to do this is that I want other classes to be able to implement my class, but still share some code with the class.
It appears from the discussion that I can’t do this without just copy-pasting the code from the mixin into my class, or requiring every subclass to mix in the code, neither of which appeals.
--
For more ways to connect visit https://dart.dev/community
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
To view this discussion on the web visit https://groups.google.com/a/dartlang.org/d/msgid/misc/40BAEA1C-9601-4C95-B2C9-49A73554CB14%40gmail.com.
I don't follow this. Let me start over.I have a class like this:class Foo {void x() {y();}void y() {print('y');}}I will have some classes that extend Foo and others that implement Foo. The ones that implement Foo will all need x(), which depends on a method in Foo.So what I want to do is to move x() to some XMixin on Foo
mixin FooMixin {void x() => y();void y();}class Foo with FooMixin {void y() => print('y');}class FooSubclass extends Foo {}class FooSubtype with FooMixin implements Foo {void y() {/* Do whatever is appropriate */}}
class FooBase {void y() => print('y');}mixin FooMixin implements FooBase {void x() => y();}class Foo extends FooBase with FooMixin {}class FooSubclass extends Foo {}class FooSubtype with FooMixin implements Foo {void y() {/* Do whatever is appropriate */}}
mixin XMixin on AbstractFoo {
void x() {
y();
}
}
abstract class AbstractFoo {
void y() {
print('y');
}
}
I mentioned that you only need `on Foo` if you must perform super-invocations (like `super.x()`) of methods declared by `Foo`. There are no super-invocations in your example so you cannot possibly need `on` anything.
On Jan 24, 2021, at 12:00 , Erik Ernst <eer...@google.com> wrote:
On the other hand, you must ensure that methods on `this` (invoked explicitly as `this.m()` or implicitly as `m()`) that you must call in the body of the mixin are statically known to exist. As I mentioned, one way to do this is to have `implements OtherClass` where `OtherClass` has the desired members, and another way is to simply declare the members that you need as abstract in the mixin. Let's take the latter first:mixin FooMixin {void x() => y();void y();}class Foo with FooMixin {void y() => print('y');}class FooSubclass extends Foo {}class FooSubtype with FooMixin implements Foo {void y() {/* Do whatever is appropriate */}}If you consider the abstract declaration `void y();` as too much copy-paste then you can use implements:class FooBase {void y() => print('y');}mixin FooMixin implements FooBase {void x() => y();}class Foo extends FooBase with FooMixin {}class FooSubclass extends Foo {}class FooSubtype with FooMixin implements Foo {void y() {/* Do whatever is appropriate */}}This is actually exactly the same class hierarchy that you mention, except that `FooBase` is concrete whereas your `AbstractFoo` is abstract (there is no need to make it abstract).
The point is that the "empty" class `class Foo extends FooBase with FooMixin {}` isn't useless: `FooBase` only needs to contain abstract declarations (so if it's helpful then you can make `FooBase.y` abstract and implement it in `Foo`), and `FooBase` only needs to contain declarations of members that the mixin methods are calling (so you could have lots of other methods in `Foo`, as long as they aren't called by any methods in `FooMixin`). Finally, `Foo` combines `FooBase` and `FooMixin`, which means that it isn't "empty", it specifies a non-empty amount of construction work.
On Jan 24, 2021, at 12:00 , Erik Ernst <eer...@google.com> wrote:On the other hand, you must ensure that methods on `this` (invoked explicitly as `this.m()` or implicitly as `m()`) that you must call in the body of the mixin are statically known to exist. As I mentioned, one way to do this is to have `implements OtherClass` where `OtherClass` has the desired members, and another way is to simply declare the members that you need as abstract in the mixin. Let's take the latter first:mixin FooMixin {void x() => y();void y();}class Foo with FooMixin {void y() => print('y');}class FooSubclass extends Foo {}class FooSubtype with FooMixin implements Foo {void y() {/* Do whatever is appropriate */}}If you consider the abstract declaration `void y();` as too much copy-paste then you can use implements:class FooBase {void y() => print('y');}mixin FooMixin implements FooBase {void x() => y();}class Foo extends FooBase with FooMixin {}class FooSubclass extends Foo {}class FooSubtype with FooMixin implements Foo {void y() {/* Do whatever is appropriate */}}This is actually exactly the same class hierarchy that you mention, except that `FooBase` is concrete whereas your `AbstractFoo` is abstract (there is no need to make it abstract).My mental model was that ‘on’ was doing what you’re here doing with ‘implements’.
Would you explain the difference?
This use of ‘implements’ is interesting. I expected that the compiler would complain about this use of ‘implements’, because the mixin clearly doesn’t implement anything from FooBase. Is it that ‘implements’ is treated differently on Mixins?
If not, my mental model of what ‘implements’ is doing is all wrong. Are these subtleties documented anywhere?
The point is that the "empty" class `class Foo extends FooBase with FooMixin {}` isn't useless: `FooBase` only needs to contain abstract declarations (so if it's helpful then you can make `FooBase.y` abstract and implement it in `Foo`), and `FooBase` only needs to contain declarations of members that the mixin methods are calling (so you could have lots of other methods in `Foo`, as long as they aren't called by any methods in `FooMixin`). Finally, `Foo` combines `FooBase` and `FooMixin`, which means that it isn't "empty", it specifies a non-empty amount of construction work.I’m trying to make my code as simple as possible for users and readers of the classes.
This involves a good deal of noise and non-obvious dancing about just to please the compiler. I want to extract a method then mix it back in, and I can only do it by introducing all this otherwise pointless infrastructure.