【Dart學習】-- Dart之泛型


一,概述    

     Dart是一種可選的類型語言。Dart中的集合默認是異構的。換句話說,單個Dart集合可以托管各種類型的值。但是,可以使Dart集合保持同質值。泛型的概念可以用來實現同樣的目的。
  泛型的使用強制限制集合可以包含的值的數據類型。這種集合稱為類型安全集合。類型安全是一種編程功能,可確保內存塊只能包含特定數據類型的數據。
  所有Dart集合都通過泛型支持類型安全實現。包含數據類型的一對尖括號用於聲明類型安全的集合。聲明類型安全集合的語法如下所示。
    通俗理解:泛型就是解決 類 接口 方法的復用性、以及對不特定數據類型的支持(類型校驗)

二,語法

Collection_name <data_type> identifier= new Collection_name<data_type>

三,使用泛型的好處

  泛型是類型安全的(意思是你必須指定數據的類型),但是它的寫法比硬編碼指定類型高效的多:

  • 類型安全

    比如讓數組只有String值,定義為List。這樣,后續代碼中,如果給數組賦值了非String類型,編譯器將提示報錯

    var names = List<String>();
    names.addAll(['Seth', 'Kathy', 'Lars']);
    names.add(42); // Error
  • 減少重復的代碼  
    泛型讓你通過一個單一類可以適配多種類型的數據操作,同時可以進行靜態代碼檢查(比如,類型安全檢查)。
    abstract class ObjectCache {
      Object getByKey(String key);
      void setByKey(String key, Object value);
    }

    上面代碼是對Object類型操作,在沒用泛型的情況下,你想對String類型操作,就得重新定義一個類

    abstract class StringCache {
      String getByKey(String key);
      void setByKey(String key, String value);
    }

    后面,你如果相對num類型操作,還得重新定義一個類。

    而泛型就可以解決上面的問題,它通過對類型參數化,實現一個類針對多種數據類型操作的適配。

    abstract class Cache<T> {
      T getByKey(String key);
      void setByKey(String key, T value);
    }

四,Dart泛型的使用

  • 使用集合

    List(通用列表)和map(通用映射)等字面量方式可以用指定類型參數。

    var names = <String>['Seth', 'Kathy', 'Lars'];
    var pages = <String, String>{
      'index.html': 'Homepage',
      'robots.txt': 'Hints for web robots',
      'humans.txt': 'We are people, not machines'
    };

    Set(通用集)和Queue(通用隊列)等構造器方式可以用指定類型參數

    void main() { 
      List <String> logTypes = new List <String>(); 
      logTypes.add("WARNING"); 
      logTypes.add("ERROR"); 
      logTypes.add("INFO");
    
      // iterating across list 
      for (String type in logTypes) { 
        print(type); 
      } 
    }
    import 'dart:collection'; 
    void main() { 
      Queue<int> queue = new Queue<int>(); 
       print("Default implementation ${queue.runtimeType}"); 
       queue.addLast(10); 
       queue.addLast(20); 
       queue.addLast(30); 
       queue.addLast(40); 
       queue.removeFirst();
    
      for(int no in queue){ 
        print(no); 
      } 
    }
  • Dart的泛型類型是在運行時綁定的,這樣,在運行時,可以知道List內具體類型

    var names = List<String>();
    names.addAll(['Seth', 'Kathy', 'Lars']);
    print(names is List<String>); // true

    注意:java中,泛型是采用擦除的方式,它在運行時,其實對象都是Object類型或者泛型的約束父類。

  • 當泛型時,希望限制參數的類型范圍,可以用extends關鍵字約束。
    class Foo<T extends SomeBaseClass> {
      // Implementation goes here...
      String toString() => "Instance of 'Foo<$T>'";
    }
    
    class Extender extends SomeBaseClass {...}

    添加約束后,只要是指定的父類或者其子類都可以作為泛型參數。

    var someBaseClassFoo = Foo<SomeBaseClass>();
    var extenderFoo = Foo<Extender>();

    也可以不指定泛型參數。

    var foo = Foo();
    print(foo); // Instance of 'Foo<SomeBaseClass>'

    不可以用限定范圍的泛型參數,這樣靜態代碼檢查器將提示錯誤。

    var foo = Foo<Object>();
  • 泛型方法

    下面是允許使用泛型方法的場景:

    In the function’s return type (T).         //返回值
    In the type of an argument (List).        //參數
    In the type of a local variable (T tmp). //局部變量

    T first<T>(List<T> ts) {
      // Do some initial work or error checking, then...
      T tmp = ts[0];
      // Do some additional checking or processing...
      return tmp;
    }
  • Dart中泛型用法
    • 泛型方法的用法
      //分類實現:同時支持返回 string類型 和int類型  (代碼冗余)
         String getData1(String value){
            return value;
         }
      
         int getData2(int value){
            return value;
         }
      
      //不確定類型:同時返回 string類型 和number類型  (放棄了類型檢查)
      
         getData(value){
            return value;
         }
      
      //泛系處理:比如:傳入number 類型必須返回number類型  傳入 string類型必須返回string類型(即減少了代碼冗余,又可以檢查類型)
         //返回T型
         T getData<T>(T value){
             return value;
         }
      //無返回值
         getData<T>(T value){
             return value;
         }
      
        void main(){
            print(getData<int>(12));
        }
    • 泛型類的用法

      //案例:把下面類轉換成泛型類,要求List里面可以增加int類型的數據,也可以增加String類型的數據。但是每次調用增加的類型要統一
      
       class PrintClass<T>{
            List list=new List<T>();
            void add(T value){
                this.list.add(value);
            }
            void printInfo(){          
                for(var i=0;i<this.list.length;i++){
                  print(this.list[i]);
                }
            }
       }
      
      main() {  
        PrintClass p=new PrintClass<int>();
        p.add(12);
        p.add(23);
        p.printInfo();
      }
    • 泛型接口的用法

      /*
      Dart中的泛型接口:
          實現數據緩存的功能:有文件緩存、和內存緩存。內存緩存和文件緩存按照接口約束實現。
          1、定義一個泛型接口 約束實現它的子類必須有getByKey(key) 和 setByKey(key,value)
          2、要求setByKey的時候的value的類型和實例化子類的時候指定的類型一致
      */
      
      abstract class Cache<T>{
        getByKey(String key);
        void setByKey(String key, T value);
      }
      
      class FlieCache<T> implements Cache<T>{
        @override
        getByKey(String key) {    
          return null;
        }
      
        @override
        void setByKey(String key, T value) {
         print("我是文件緩存 把key=${key}  value=${value}的數據寫入到了文件中");
        }
      }
      
      class MemoryCache<T> implements Cache<T>{
        @override
        getByKey(String key) {   
          return null;
        }
      
        @override
        void setByKey(String key, T value) {
             print("我是內存緩存 把key=${key}  value=${value} -寫入到了內存中");
        }
      }
      void main(){
           MemoryCache m=new MemoryCache<Map>();
           m.setByKey('index', {"name":"張三","age":20});
      }

       


        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM