Mixin is a very important concept in Dart, especially for the Coder who has not been exposed to this concept. When I read the source code recently, due to the lack of familiarity with mixin, I made a lot of mistakes in understanding, so this article introduces the concept of mixin.
Dart and Engine versions:
Engine • revision ae90085a84 Tools • Dart 2.10.4
Please note the version, different versions may differ.
Let’s start with the official definition:
Mixins are a way of reusing a class’s code in multiple class hierarchies.
Mixins are a way to reuse class code in multiple class hierarchies.
Take a look at the Wiki explanation:
In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin’s methods depends on the language. Mixins are sometimes described as being “included” rather than “inherited”.
Mixins encourage code reuse and can be used to avoid the inheritance ambiguity that multiple inheritance can cause (the “diamond problem”), or to work around lack of support for multiple inheritance in a language. A mixin can also be viewed as an interface with implemented methods. This pattern is an example of enforcing the dependency inversion principle.
Translation:
In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes, without having to be their parent. How these other classes gain access to mixin methods depends on the language. Mixed elements are sometimes described as “containing” rather than “inheriting”.
Mixins encourage code reuse, and can be used to avoid inheritance ambiguity that multiple inheritance can cause (the “diamond problem”), or to address insufficient support for multiple inheritance in languages. Blending can also be thought of as an interface to an implemented method. This pattern is an example of enforcing the dependency inversion principle.
Mixins are a solution to the problem of multiple inheritance. Mixins are a solution to the problem of multiple inheritance.
When should I use Mixins
The following scenarios are available:
Define a base class Person that has a method to eat.
There are three actual people A, B, and C, all of whom inherit from Person, but with different skills:
- A: You can sing and dance
- B: Can dance and write code
- C: Can sing and write code
In the above scenario, singing, dancing, and writing code are skills that not everyone can learn, so it is not appropriate to define them in Person. If they are defined as a class, they cannot inherit Person from singing, dancing, and writing code at the same time. If singing, dancing, and writing code is defined as Interface, Then A, B and C should implement their respective methods.
So how do you do that? Here comes Mixins.
Define a Person base class and function class to sing, dance, and write code:
class Person {
eat() {
print('Person eat'); }}class Dance {
dance() {
print('Dance dance'); }}class Sing {
sing() {
print('Sing sing'); }}class Code {
code() {
print('Code code'); }}Copy the code
Define A, B, C:
class A extends Person with Dance.Sing {}
class B extends Person with Sing.Code {}
class C extends Person with Code.Dance {}
Copy the code
Note: Mix the with keyword.
Use:
A a = A();
a.eat();
a.dance();
a.sing();
Copy the code
Output log:
flutter: Person eat
flutter: Dance dance
flutter: Sing sing
Copy the code
You can see that there are Dance and Sing related methods in A.
Dance is a class. What if I add a constructor to it?
Add a constructor to Dance, modify it as follows,
A and C cannot be compiled.
Obviously, classes that require mixins cannot define constructors.
So the mixin keyword is typically used for classes that require mixins:
Add the qualifier, using the keyword ON
Continuing with the above scenario, define a dog class that can also mix Dance, Sing, and Code.
class Dog with Code{}
Copy the code
However, Code is a human-only skill, and we don’t want the Dog class to be mixin, so we add a qualification to Code:
Use the keyword on to restrict Code only to Person or a subclass mixin.
At this point, Dog cannot mixin Code.
After adding a qualification, we can override its methods. Code overrides the Person method:
Super means the method that calls the parent class (Person).
How do I handle cases where multiple classes have the same method
Suppose there are two classes D and D1, with the same method D, E mixin D and D1:
At this point, call the e.d method:
E e = E();
e.d();
Copy the code
Output:
flutter: D1 d
Copy the code
Change the order of D and D1:
class E with D1.D {}
Copy the code
Output:
flutter: D d
Copy the code
Add d method to E:
Output:
flutter: E d
Copy the code
That means the method in E overrides the original.
The d method in E can call super.d()
Output:
flutter: D d
flutter: E d
Copy the code
Suppose I now have F, G, and H classes, all of which have a method,
Classes are defined as follows:
So what value will be printed:
The answer is:
flutter: G a
Copy the code
Remember: when mixing classes, the multiple classes are linear, which is why their common methods do not conflict. The order of mixing is very important, because it determines the processing logic of the same methods when mixing.
Look at the mixing of FG again:
FG inherits H and mixes F and G. For the same method, the priority is G > F > H, so there is a common method A, and the last method is a in class G.
So what happens if FG also has method A in it?
If the same method exists in (FG), then the priority is FG > G > F > H. Super.a () performs method A in G.
Output result:
flutter: G a
flutter: FG a
Copy the code
To get more complicated, see the following hybrid relationship:
BB is an abstract class, with a constructor, init method, GB and PB are a mixed type, limit BB or its subclasses can mix, WFB inherits BB, and mix GB and PB, WFB creates a WFB object,
WFB wfb = WFB();
Copy the code
What is the output?
flutter: BB Constructor
flutter: BB init
flutter: GB init
flutter: PB init
Copy the code
The init method of PB should only be called.
Super.init () is called in the init method of PB, but super.init() is called in the init method of PB, which is important. GB calls the init method in BB via super.init, so the final output is the result above.
This must be understood because the entry function to the Flutter Framework runApp is in this form:
WidgetsFlutterBinding. The ensureInitialized method is as follows:
The WidgetsFlutterBinding mix structure is as follows:
class WidgetsFlutterBinding extends BindingBase with GestureBinding.SchedulerBinding.ServicesBinding.PaintingBinding.SemanticsBinding.RendererBinding.WidgetsBinding {
Copy the code
BindingBase and its constructor are as follows:
It executes the initInstances and initServiceExtensions methods. Look at the following order of mixing:
Execute its initInstances and initServiceExtensions methods (if any) from back to front, Because initInstances and initServiceExtensions method executed first. Super initInstances () and super initServiceExtensions (), so the last execution of order: BindingBase -> GestureBinding -> SchedulerBinding -> ServicesBinding -> PaintingBinding -> SemanticsBinding -> RendererBindinsg – > WidgetsBinding.
type
F, G, H, what is the type of FG? What is the output of the following judgment?
Output:
flutter: FG is F : true
flutter: FG is G : true
flutter: FG is H : true
Copy the code
So the blended type is a subtype of the superclass.
conclusion
- Mixins allow us to add the “functionality” of a parent class to this class without having to inherit the parent class, having one parent and multiple mixin components in the same class.
- Mixins may not declare any constructors.
- Add qualifications to Mixins using the on keyword.
- Mix with the with keyword, which can be followed by class, abstract class, and mixin types.
- Mixins are not multiple inheritance; rather, they are simply a way to reuse code in a class across multiple hierarchies without extending it.
communication
Collect the PDF of “330 Controls” and “Flutter Practice” in the blog. Address: laomengit.com