美文网首页Flutter 入门与实战Flutter圈子
在 Dart 中更好地使用类和 Mixin

在 Dart 中更好地使用类和 Mixin

作者: 岛上码农 | 来源:发表于2022-05-10 18:51 被阅读0次

    Dart 是一门“纯”面向对象的编程语言,其中所有的对象都是类的实例。但是 Dart 并不要求所有代码都定义在一个类中。我们可以在一个类的外面定义顶级变量、常量、函数 —— 就像面向过程语言那样。正式因为这样,Dart 的编码会有些特殊的建议。

    建议1:如果一个抽象类只有一个函数,那么直接定义函数会更好

    假设我们需要一个回调函数或使用一个函数,在像 Java 那样的语言中你需要定义一个类。但是,在 Dart 中,如果仅仅是一个函数,定义类反而使得代码不好维护。这个时候建议直接使用 typedef 来定义函数别名。

    // 正确示例
    typedef Predicate<E> = bool Function(E element);
    
    // 错误示例
    abstract class Predicate<E> {
      bool test(E element);
    }
    

    建议2:如果一个类只有静态变量或函数的话,那么直接定义顶级的常量和函数来替换这种方式

    Java 或 C#中,如果要定义常量的话通常需要定义一个静态常量类来做,例如:

    // Java 代码
    public class ConstParams {
        public static int maxLength = 256;
        public static int minLength = 5;
    }
    

    这样做的好处是假设静态常量名在多个类中定义的话,可以通过命名空间避免冲突。那么对于 Dart 而言,在类外面定义的变量、函数可以使用库(library)作为命名空间来区分,因此这样的话即便出现变量名一致也不会冲突。

    // const_params.dart
    const int maxLength = 256;
    const int minLength = 5;
    
    // test.dart
    import 'const_params.dart' as ConstParams;
    
    void main() {
       print('max: ${ConstParams.maxLength}');
    }
    

    因此在 Dart中,下面的写法是不推荐的。

    class ConstParams {
      static const maxLength = 256;
      static const minLength = 256;
    }
    

    当然,这并不是一个硬性规定,比如如果有一组相同类的常量的话,那么使用类会使得代码的可读性更高,例如下面颜色这个例子。

    class Color {
      static const red = '#f00';
      static const green = '#0f0';
      static const blue = '#00f';
      static const black = '#000';
      static const white = '#fff';
    }
    

    建议3:不要轻易使用继承

    这个在很多语言都有介绍过,继承应该仅在子类符合“is a”父类的关系的时候才使用。比如 Dog 类可以继承 Animal 类,但是这个也应该限于父类足够抽象,没有太多个性化特征,而且未来的改动也极少。

    使用继承确实可以减少编码,但是基类的任何变动都可能导致你的子类代码异常。如果你的子类很多的话,那么维护起来是相当恐怖的。一个比较好的建议是,对于支持继承的基类统一命名表名该类可以继承,比如 IterableBase。同时,对于基类一定写好文档,方便想继承该类的子类清楚知道可能的影响。

    建议4:不要使用 implements 实现非接口类

    接口类的定义的好处是可以在多种实现方式中切换而无需更改代码,在依赖注入型的框架或代码结构中会经常使用面向接口编程的方式。

    如果一个类的设计目的不是用作接口的,那么使用 implements 来实现这个类的方法的话是很奇怪的行为。往这个类中加入成员变量不会产生什么问题,但是如果新增方法的话就会意味着代码会出错。因此,如果要采取面向接口编程,定义的接口类应该是一个“虚”类,只有必要方法声明,而没有其他属性。同时,这个类应该有良好的文档注释,以便实现类能够知道如何准确地实现对应的接口。

    建议5:优先使用 mixin 关键字定义 mixin 类型

    在 Dart 2.1.0版本以前,并没有关键字 mixin,需要混入其他特性的话,需要使用 class 定义混入类型。而在 Dart 2.1.0版本后,引入了 mixin 专门定义混入类型,这样使得语义更加清晰,可以对比一下下面的两种实现方式。很显然,使用 mixin 会让我们更清晰地知道这是一个混入类型,而不会当做一个类来使用。官方的建议是,自 Dart 2.1.0版本以后,不应该再使用 class 关键字定义混入类型,以避免出现随意混入,导致代码不好维护。

    // mixin 方式
    mixin SpeakEnglishMixin {
      void speakEnglish() {
        print('I can speak English fluently');
      }
    }
    
    // class 方式
    class SpeakEnglishMixin {
      void speakEnglish() {
        print('I can speak English fluently');
      }
    }
    

    此外,mixin 也可以使用 on 关键字指定只适用于特定的类,从而限定范围,避免滥用。 下面声明的这个例子中 SpeakEnglishMixin 只能用于 Person 子类混入。

    mixin SpeakEnglishMixin on Person {
      void speakEnglish() {
        print('I can speak English fluently');
      }
    }
    

    总结

    本篇介绍了 Dart 相比其他面向对象语言的一些独有特性,例如类外面的变量、函数定义,mixin 等。其实 Dart 可以说是综合了面向对象语言和动态语言的优点,更贴近现代化编程语言的特性。但编码工作万变不离其宗,我们利用 Dart 的特性应该是为了编写更好维护的代码,而不是滥用误用其新特性。

    相关文章

      网友评论

        本文标题:在 Dart 中更好地使用类和 Mixin

        本文链接:https://www.haomeiwen.com/subject/iexrurtx.html