-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Support mixins #33
Comments
Removed Type-Defect label. |
This comment was originally written by [email protected] Added Triaged label. |
This comment was originally written by [email protected] The same (here: your example given) could be realized by just inheriting CollegeStudent from Worker... Basically you are just asking for multiple inheritance at the class level. |
This comment was originally written by [email protected] The given example has an obvious diamond problem (What does CollegeStudent.schedule() return?), and thus appears to just be multiple inheritance in disguise. My understanding of traits (based on Scala's traits http://www.scala-lang.org/node/126 ) is that they're just interfaces that can contain method bodies. These method bodies can only access the other methods and accessors that the trait declares. When a class is extended with a trait, the defined methods are automatically implemented in that class. It is technically a subset of multiple inheritance, but much it's easier to think of as an extension of interfaces that can reduce code in situations where every implementing class would have the same definition of one of the interface's methods. I don't think Dart should have Multiple Inheritance due to the complexity of implementing it in a static compiler, but Traits are quite easy to implement, and provide a lot of the flexibility otherwise desired from Multiple Inheritance. |
I'm renaming the issue so that its clear what this is about. The confusion between mixins (or their close cousins, traits) and interfaces is not uncommon, but it is confusion nonetheless. Interfaces should not become mixins, but it would be very nice to support mixins in the language. That is something we are considering, but cannot give any commitments on at this time. Changed the title to: "Support mixins". |
Set owner to @gbracha. |
This comment was originally written by [email protected] Another option is to just allow to add code in interface but no field. |
Marked this as blocking #1492. |
This comment was originally written by [email protected] +1 also think we need something in this area to be able to succinctly add helpers to existing types. If not traits or mixins than something ala C# methods, or Go langs interface methods. Either way being able to enhance existing types prevents unnecessary forced abstractions (for devs who inheirt types just to be able to add their own helpers), promote more readable and require less code at the call-site, e.g: StingUtils.indent(Helper.toCustomFormat(obj)); obj.toCustomFormat().indent(); |
This comment was originally written by @MarkBennett Taken from a G+ post I did on this topic... https://plus.google.com/104431949275766772757/posts/BUUeiqhebJC <rant> Having had this experience developing large apps in languages with (Ruby, JS, Scala) and without (Java, Python) support for mixins, I am strongly in favour of this feature being added to +Dart : Structured web apps for the following reasons: First, Interfaces are useful for encouraging well defined interactions between application elements, but they also introduce significant places for code duplication as the interface is implemented in different classes. Define once, write many times makes re-factoring a challenge as the same implementation appears many places throughout the codebase. Mixins address this by providing a shared default implementation which can be extended by classes only when necessary. Defining code in one place reduces the size of the code base and less code to maintain means less potential for unhandled bugs. Second, mixins can be implemented in such a way that method lookups can all be resolved at compile time preventing any extra lookups during method calls and other performance considerations. This also allows tools to identify potentially conflicting mixin methods. This is not true if implemented using something like Ruby style mixins, but would be true of Scala style traits. Third, there are well understood ways to consistently resolve method name conflicts between mixins. As long as method resolution is expressly covered in the specification, then tooling can support it and assist developers in understanding which methods will be called when. Admintedly, there are some rough edges with mixins which can result in some confusion. For example, consider the case where Mixin A and B both implement a #to_s () method. Mixin A and B also both use the #to_s () method in their default implementations expecting a different value to be returned. When these mixins are included in Class X, which #to_s () implementation is used, and which #to_s () method is resolved in the default implementations of Mixin A and B? This situation is theoretical, and my experience in Ruby and JavaScript has taught me that it's not something most developers are likely to experience in real applications, but it is a possibility which will need to be handled by the spec. This is one reason why I firmly believe that any implementation of mixins needs to be able to resolve all Class methods at compile time so developer tools can identify and assist developers in resolving issues like this before code is released. To wrap-up I really feel that mixins are a valuable part of a modern language, and a tool which can be used to reduce the size and complexity of a code base. They're also a great way to share rich behaviours across a broad range of objects. For example, consider the power of things like the Enumerable mixin in Ruby. Thanks for reading this post, and taking the time to reflect on the future of web programming. Excited to see how responsive and accessible the Dart team has been making themselves. </rant> |
This comment was originally written by [email protected] +1 traits/mixins are really missing from the language |
This comment was originally written by [email protected] Traits can be very useful dealing with specialized collections, which have multiple implementations. Say you have a collection Customers, with a method fromCountry(Country c). The implementation is would be something like => _internalList.filter((customer) customer.country == c); If you have multiple collection classes for Customer, say an Immutable and Mutable variant, or maybe a Set and List, you can simply inherit the trait, and have fromCountry implemented in both. No subclassing, wrapping or a seperate class with static methods is required this way, simplifying code. |
Added apr30-triage label. |
Removed apr30-triage label. |
Added triage1 label. |
This comment was originally written by [email protected] I originally articulated my thoughts on why we need mixins here: https://github.com/mythz/DartMixins#the-need-for-mixins but I'll re-post my thoughts here in-case the link gets bit-rotted... Basically the problem is that all core types in Dart (i.e nums, ints, strings, Lists, Maps, etc) are interfaces (which is good) but also means defining additional functionality causes un-due friction since it forces all interface implementors the burden of providing an implementation. i.e. You have two opposing forces:
If Dart supported Mixins it would allow a single implementation to be shared by all collections. For an illustrative example let's look at the Collection interface: Collection extends Iterable Out of these only the Iterable interface and length() getter are required since the rest of the API could be added via Mixins, e.g: Collection c = ..; I don't think the current convention of plurazing the Interface type is a great convention since the core Dart library 'takes' the most obvious name |
This comment was originally written by @tomaszkubacki i think c# way is way better with extension methods because no need for new keywords except using already known "this" e.g adding isEmail method to String type could look like: bool isEmail(this String s) => { check_if_email_logic_comes_here } then usage: String s = "[email protected]" Most important reason to add extension methods is that they allow extend core lib types with less common or domain specific functionality. Also building whole new libs as extension methods is widely used in other languages e.g ServiceStack.OrmLite is a set of high level orm extension methods over low level IDbCommand. |
This comment was originally written by [email protected]
FYI, it was already explained a lot of times that C#-style extension methods are a no-go for Dart, because they depend on types. One of Dart's core principles is that type annotations never affect runtime semantics, which is pretty much incompatible with the very idea of extension methods. |
This comment was originally written by @ahmetaa Not an expert on this issue but there is also Java 8 defender methods to check |
Changes: ``` > git log --format="%C(auto) %h %s" 7c73ec8..3e695bc https://dart.googlesource.com/test_process.git/+/3e695bc Merge pull request #33 from dart-lang/repository_field https://dart.googlesource.com/test_process.git/+/da43a51 populate the repository field https://dart.googlesource.com/test_process.git/+/18d26e5 Bump actions/checkout from 2 to 3 (#32) https://dart.googlesource.com/test_process.git/+/5ec59cb Merge pull request #30 from scheglov/meta-1.3.0 https://dart.googlesource.com/test_process.git/+/b33c7a2 Revert to 'meta: ^1.3.0'. https://dart.googlesource.com/test_process.git/+/4c55feb Merge pull request #29 from scheglov/meta-2.0.0 https://dart.googlesource.com/test_process.git/+/6b0c025 Update 'meta' constraint to '>=1.3.0 <3.0.0'. https://dart.googlesource.com/test_process.git/+/7ac00ea Update test-package.yml (#28) https://dart.googlesource.com/test_process.git/+/653e3ba Bump dart-lang/setup-dart from 0.3 to 1 (#27) https://dart.googlesource.com/test_process.git/+/d789476 Add dependabot https://dart.googlesource.com/test_process.git/+/52732de Merge pull request #26 from dart-lang/franklinyow-patch-1 https://dart.googlesource.com/test_process.git/+/6c13ab5 Update LICENSE https://dart.googlesource.com/test_process.git/+/1c9aadb Fix formatting (#25) https://dart.googlesource.com/test_process.git/+/c7416f1 Prepare to publish (#24) ``` Diff: https://dart.googlesource.com/test_process.git/+/7c73ec8a8a6e0e63d0ec27d70c21ca4323fb5e8f~..3e695bcfeab551473ddc288970f345f30e5e1375/ Change-Id: I2bf20858f603f34a3a22bfd19653014035ff4e3c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/245226 Reviewed-by: Kevin Moore <[email protected]> Commit-Queue: Devon Carew <[email protected]>
This issue was originally filed by [email protected]
Traits are interfaces on crack.
Really, it's what interfaces should have been. This would allow developers to code much less.
Traits doesn't have problems of multiple inheritance.
It would be great to have their support in dart. Something like
abstract class Person {
Schedule schedule()
}
trait Student extends Person {
private var classSchedule = ...
schedule() => classSchedule
learn() => ...
}
trait Worker extends Person {
private var workSchedule = ...
schedule => workSchedule
work() => ...
}
class CollegeStudent extends Student with Worker {
// ...
}
The text was updated successfully, but these errors were encountered: