Flutter Dart mixins 探究

0x00 前言

mixins做爲Flutter的重要特性,值得好好研究一下bash

0x01 mixins的定義

mixins的中文意思是混入,就是在類中混入其餘功能。ide

Dart中的定義是:函數

Mixins are a way of reusing a class’s code in multiple class hierarchies.
複製代碼

Mixins是一種在多個類層次結構中複用類代碼的方法。post

能夠看出Mixins最重要的功能是複用代碼,咱們先看下JAVA,複用代碼的方式有哪些:ui

  1. 繼承spa

    子類能夠複用父類的方法和屬性,可是JAVA裏的繼承只能單繼承。code

  2. 組合對象

    將要複用的代碼,封裝成類A,讓其餘類持有A的實例,看上去貌似解決了複用代碼的問題,可是一方面,每一個類持有的A的實例是不一樣的,有多少個類,就總共有多少個A的實例,並且另外一方面,即便A使用單例,使用起來也很不方便。繼承

  3. 接口接口

    定義一個接口interface,類實現interface,這樣雖然接口是同一個,可是實現倒是分散的,能複用的代碼是有限的。

因此在JAVA裏想要複用代碼,限制是不少的。

這就有了mixins的概念,mixins最先的根源來自於Lisp,由於Dart也受到smalltakk的影響,因此Dart引入了mixins的概念,

在維基百科中有對mixins最準確的定義:

在面向對象的語言中,mixins類是一個能夠把本身的方法提供給其餘類使用,但卻不須要成爲其餘類的父類。
複製代碼

mixins是要經過非繼承的方式來複用類中的代碼。

這裏舉個例子,有一個類A,A中有一個方法a(),還有一個方法B,也想使用a()方法,並且不能用繼承,那麼這時候就須要用到mixins,類A就是mixins類(混入類),類B就是要被mixins的類,對應的Dart代碼以下:

類A mixins 到 B

class A {
  String content = 'A Class';

  void a(){
    print("a");
  }
}

class B with A{

}

B b = new B();
print(b.content);
b.a();
複製代碼

輸出是:

A Class
a
複製代碼

將類A mixins 到 B,B可使用A的屬性和方法,B就具有了A的功能,可是須要強調的是:

  1. mixins的對象是類
  2. mixins毫不是繼承,也不是接口,而是一種全新的特性
  3. 能夠mixins多個類
  4. mixins的使用須要知足必定條件

0x02 with

mixins要用到的關鍵字 with

怎麼來理解with呢?很簡單:

繼承 -> extends

mixins -> with

繼承和mixins是同樣的,是語言的特性,with和extends是關鍵字。

0x03 使用mixins的條件

由於mixins使用的條件,隨着Dart版本一直在變,這裏講的是Dart2.1中使用mixins的條件:

  1. mixins類只能繼承自object
  2. mixins類不能有構造函數
  3. 一個類能夠mixins多個mixins類
  4. 能夠mixins多個類,不破壞Flutter的單繼承

0x04 一個類能夠mixins多個mixins類

看下面代碼:

class A {
  void a(){
    print("a");
  }
}

class A1 {
  void a1(){
    print("a1");
  }
}

class B with A,A1{

}

B b = new B();
b.a();
b.a1();
複製代碼

輸出是:

a
a1
複製代碼

可是,若是A和A1的方法相同,並且調換A和A1的順序,在被mixins的類中實現同一個方法呢,看下面的代碼:

class A {
  void a(){
    print("a");
  }
}

class A1 {
  void a(){
    print("a1");
  }
}

class B with A,A1{

}

class B1 with A1,A{

}

class B2 with A,A1{
  void a(){
    print("b2");
  }
}

class C {
  void a(){
    print("a1");
  }
}

class B3 extends C with A,A1{

}

class B4 extends C with A1,A{
  
}

class B5 extends C with A,A1{
  void a(){
    print("b5");
  }
}

B b = new B();
B1 b1 = new B1();
B2 b2 = new B2();
B3 b3 = new B3();
B4 b4 = new B4();
B5 b5 = new B5();



b.a();
b1.a();
b2.a();
b3.a();
b4.a();
b5.a();
複製代碼

會是什麼樣的結果呢?

0x05 mixins的實現原理

Mixins in Dart work by creating a new class that layers the implementation of the mixin
on top of a superclass to create a new class — it is not 「on the side」 but 「on top」 of
the superclass, so there is no ambiguity in how to resolve lookups.
複製代碼

class B3 extends C with A,A1{

}
複製代碼

爲例,能夠分解爲:

class CA = C with A;
class CAA1 = CA with A1;

class B3 extends CAA1{
    
}
複製代碼

mixins不是多繼承

Mixins is not a way to get multiple inheritance in the classical sense. Mixins is a way to abstract and reuse a family of operations and state. It is similar to the reuse you get from extending a class, but it is compatible with single-inheritance because it is linear.
複製代碼

因此輸出結果是:

a1
a
b2
a1
a
b5
複製代碼

0x06 mixins類型

mixins的實例類型是什麼?

很簡單,mixins的類型就是其超類的子類型,因此:

B3 b3 = B3();
print(b3 is C);
print(b3 is A);
print(b3 is A1);
複製代碼

都會爲true

0x07 on

on關鍵字,以前是用於try catch,用於指定異常的類型的。

此次,on只能用於被mixins標記的類,例如mixins X on A,意思是要mixins X的話,得先接口實現或者繼承A。這裏A能夠是類,也能夠是接口,可是在mixins的時候用法有區別.

想看接口的請看個人這篇文章Flutter Dart語法(1):extends 、 implements 、 with的用法與區別

  1. on 一個類

用繼承:

lass A {
  void a(){
    print("a");
  }
}


mixin X on A{
  void x(){
    print("x");
  }
}


class mixinsX extends A with X{

}
複製代碼
  1. on 的是一個接口:

得首先實現這個接口,而後再用mix

class A {
  void a(){
    print("a");
  }
}


mixin X on A{
  void x(){
    print("x");
  }
}

class implA implements A{
  @override
  void a() {
    // TODO: implement a
  }

}

class mixinsX2 extends implA with X{

}
複製代碼
相關文章
相關標籤/搜索