Flutter - Dart 基础(泛型)

396 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

泛型

  • Dart 中的泛型和其他语言中的泛型意思一样。当类型暂时不确定,可以使用泛型占位,只有等到调用函数时才能确定具体类型。通俗的讲,泛型就是占位符
  • 使用泛型的好处
    • 适当的泛型可以更好的帮助代码生成
    • 使用泛型可以减少代码重复

泛型定义集合

  • map 使用泛型

    void main(List<String> args) {
    
        // 创建 Map
        var map = {"name": "dart", "age": 12};
        print(map.runtimeType); // _InternalLinkedHashMap<Object, Object>
    
         // 使用泛型,定义 map 进行约束, 在 map 中,value 必须是字符串
        Map<String, String> dic1 = {'name': 'why', 'age': 18}; // 报错,map中必须是字符串
    
        var dic2 = <String, String>{'name': 'why', 'age': 18}; // 报错,map中必须是字符串
    }
    
  • list 使用泛型

    void main(List<String> args) {
    
        // 创建 list
        var list = ['a', 'b', 'c', 1, 2];
        print(list.runtimeType);  // List<Object>
    
    
        // 使用泛型,定义 list 进行约束, 在 list 只能添加字符串
        var strList = <String>["a", "b", "c", 1, 2];  // 报错,数组中必须是字符串
        
        List<String> strList1 = <String>["a", "b", "c", 1, 2];  // 报错,数组中必须是字符串
    
    }
    

泛型函数

  • 函数的泛型使用了占位类型名(在这里用字母 T 来表示)来代替实际类型名(例如 IntString)。占位类型名没有指明 T 必须是什么类型,但是它指明了传参和返回值必须是同一类型 T,无论 T 代表什么类型。只有 getData() 函数在调用时,才会根据所传入的实际类型决定 T 所代表的类型

  • 泛型函数和非泛型函数的另外一个不同之处,在于这个泛型函数名 getData() 后面跟着占位类型 (T),并用尖括号括起来 <T>。这个尖括号告诉 Dart 那个 TgetData() 函数定义内的一个占位类型名,因此 Dart 不会去查找名为 T 的实际类型

//非泛型函数
String getData(String value) {
    return value;
}


num getData(num value) {
    return value;
}

//泛型函数
T getData<T>(T value) {
    return value;
}

泛型类

定义一个类,但是并不确定使用者希望使用的是 intdoubleString,这个时候如何定义呢?

  • 不使用泛型

    class LogClass {
        var list = <num>[];
        void add(num value) {
            list.add(value);
        }
        void logInfo() {
            for (var i = 0; i < list.length; i++) {
                print(list[i]);
            }
        }
    }
    
    void main(List<String> args) {
        final log = LogClass();
        log.add(1);
        log.add(2);
        log.logInfo();
    }
    
    class LogClass {
        var list = <String>[];
            void add(String value) {
            list.add(value);
        }
        void logInfo() {
            for (var i = 0; i < list.length; i++) {
                print(list[i]);
            }
        }
    }
    
    void main(List<String> args) {
        final log = LogClass();
        log.add("1");
        log.add("2");
        log.logInfo();
    }
    
  • 使用泛型

    class LogClass<T> {
        var list = <T>[];
        void add(T value) {
            list.add(value);
        }
    
        void logInfo() {
            for (var i = 0; i < list.length; i++) {
                print(list[i]);
            }
        }
    }
    
    
    void main(List<String> args) {
        final log = LogClass();
        log.add(1);
        log.add(2);
        log.logInfo();
        
        
        final log1 = LogClass();
        log1.add("1");
        log1.add("2");
        log1.logInfo();
    }
    
  • 类型约束。类型约束可以指定一个类型必须继承自指定类。比如下面这个泛型类,指定了 T 必须是 num 的子类

    class LogClass<T extends num> {
        var list = <T>[];
        void add(T value) {
            list.add(value);
        }
    
        void logInfo() {
            for (var i = 0; i < list.length; i++) {
                print(list[i]);
            }
        }
    }
    
    void main(List<String> args) {
        final log = LogClass();
        log.add(1);
        log.add(2);
        log.logInfo();
        
        
        final log1 = LogClass();
        log1.add("1");
        log1.add("2");
        log1.logInfo();
    }