-
Notifications
You must be signed in to change notification settings - Fork 214
Can we have mixin class
?
#31
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
Comments
Flagging this at the declaration site would require whole-program analysis, which analyzer doesn't currently do, and a closed-world assumption, which analyzer doesn't make. We might be able to relax the lint so that classes that do not use |
That's partially why I filed the issue. We want to make sure that this lint is useful when Flutter goes stable. However, what to do about it depends on the language direction w.r.t. non-super-mixins. |
I would love to remove the ability to derive mixins from classes entirely, for all the reasons you mention. The relation between a mixin application and the mixin class is tighter than the one between a sub-class and its super-class. If you use a class as a mixin, any number of otherwise innocuous changes can break the mixin application, so using any class as a mixin, which is not intended as a mixin, is highly fragile and discouraged. Any class in the SDK that is not named There is no good solution that doesn't remove the ability to derive a mixin from a class. Marking classes as non-mixinable requires the author to think about the issue at all, which is putting the responsibility in the wrong place. Having to mark classes as mixin-able is better handled by just converting the class to a mixin declaration directly. There is no reason to have a The obvious problem with removing class-derived mixins is migration. We can't migrate all existing code. We can't detect whether a class is intended as a mixin, we certainly can't detect whether it's used as a mixin (unless we know all Dart code in the world). So, this sounds like a migration problem that requires opt-in. If we get opt-in language features, then opting into "declared-mixins-only" would prevent any class in the opted-in code from being used as a mixin, and would prevent that code from using any class as a mixin. Opting in would be a breaking change, in case someone actually uses the class as a mixin. |
FWIW |
@Hixie in flutter/plugins#797 (comment) you mention that |
Simplicity. |
Just chatted offline with @Hixie. We are not looking for any extra properties of This is good! I think this allows us to remove the ability to derive a mixin without having to update user code. To do that we will have to overload what Imagine this declaration: class Foo extends Bar The compiler first checks whether If class Foo extends Object with Bar More generally, If This approach will allow Flutter to convert its classes-meant-to-be-mixins from LintingAnother issue that came up in the conversation is that while we are OK with converting our classes-meant-to-be-mixins to the So instead, could we somehow have the lint only check for mis-uses of our classes? Example: // material.dart
class FlatButton { ... }
// snail_racing_app.dart
class SnailButton extends Widget with FlatButton { ... }
// ^
// ERROR: FlatButton is a class, not a mixin
class Foo { ... }
// This is fine. It's their own shenanigans.
class Bar extends Object with Foo { ... } IOW, we'd like users to deal with their own code migrations on their own. We prefer that we not use Flutter as a mixin police. |
Lints are only run over the code in a package if the package opts in to the lint in the analysis options file. Users that have a package that depends on 'flutter' will not get any lint warnings about using classes in a with clause unless they explicitly enable the lint. So, you can't cause lint warnings for your users.
For the same reason, you can't do that, either. You can't enable a lint in packages that depend on 'flutter'. But I think that the behavior you describe is only one way of accomplishing your real goal, which is to control how users can use the API you provide. The best solution I know of would involve language support that we don't have. The only other alternative I can think of at the moment is to implement a hint that is enabled everywhere and that is specific to code that depends on 'flutter'. That seems like a horrid hack to me, but I don't have a better suggestion at this point. |
We select the default lints for our users, so we actually can cause them whatever trouble we want to cause them. :-) |
Yeah, |
I'm closing this issue. I have an alternative proposal: #32 (based on #31 (comment)) |
A mixin class is a non-super-mixin that allows extension. This is already supported in Dart (you just use the
class
keyword). The problem is that such mixins do not prevent unintentional breaking changes. For example:super
call to the classThese are all valid changes to normal Dart classes, but are breaking to a mixin. A dedicated class mixin declaration could prevent these issues by restricting what you can do with the class, similar to the restrictions placed on the plain
mixin
(which is allowed to be a super-mixin).Strawman proposal:
One example of such a mixin in Flutter is WidgetsBindingObserver.
prefer_mixin
lintThe current situation makes
prefer_mixin
lint unusable because the lint shows up at the usage site (thewith
clause), not at the mixin declaration site. IOW, the lint does not encourage the author of the mixin to change the declaration of the mixin, but asks the user of the mixin to use something else, which may not be possible.Alternatively: remove this capability
If we don't like this idea in general, we should be clearer about the removal of this capability so we can start cleaning up our code now. Currently the spec only says that it may potentially be removed. However, that means our users will have to live with these quirks for a long time. Flutter will declare API stability soon and it will be hard to change this in the future.
@Hixie @lrhn @leafpetersen @eernstg
The text was updated successfully, but these errors were encountered: