泛型函數

泛型,即「參數化類型」。一提到參數,最熟悉的就是定義方法時有形參,而後調用此方法時傳遞實參。那麼參數化類型怎麼理解呢?顧名思義,就是將類型由原來的具體的類型參數化,相似於方法中的變量參數,此時類型也定義成參數形式(能夠稱之爲類型形參),而後在使用/調用時傳入具體的類型。 ——來自百度typescript

自我理解:泛型函數就是,你定義函數時候,是萬能類型。在調用的時候,只要你把具體的類型傳進去就好。好處呢,就是代碼的複用,減小代碼量。編程

在面向對象的語言中都是有泛型的這個概念和實現的。好比說:JAVA、C#、C++、TypeScript等等。數組

其實泛型是用的很普遍的,特別是在寫底層框架的時候。當你們去看源碼的時候,會看到不少泛型。最近的工做中也用到了泛型,算是寫底層吧,由於給別人調用。bash

工做需求是這樣的 ,使用TCP/IP協議,從客戶端發送 「結構體」到服務端。通常都是會將數據轉化成byte[],再進行數據的傳送。查資料和用泛型改造後:框架

C#代碼ide

// 結構體轉byte數組
public byte[] StructToBytes<T>(T structParams)
{
    var size = Marshal.SizeOf(structParams);
    var buffer = Marshal.AllocHGlobal(size);
    try
    {
        Marshal.StructureToPtr(structParams, buffer, false);
        var bytes = new byte[size];
        Marshal.Copy(buffer, bytes, 0, size);
        return bytes;
    }
    finally
    {
        Marshal.FreeHGlobal(buffer);
    }
}
	
// 結構體轉byte數組
public static T BytesToStruct<T>(byte[] arr) where T : new()
{
    // where後面的泛型約束:參數須要有一個無參的構造函數
    T structType = new T();
    var size = Marshal.SizeOf(structType);
    var ptr = Marshal.AllocHGlobal(size);

    Marshal.Copy(arr, 0, ptr, size);
    structType = (T)Marshal.PtrToStructure(ptr, structType.GetType());
    Marshal.FreeHGlobal(ptr);
    
    return structType;
}
複製代碼
public struct TestStruct0
    {
        public int count;
        public string key;
    }  
    public struct TestStruct1
    {
        public int count1;
        public string key1;
    }
    // testStruct0 爲實例
    StructToBytes<TestStruct0>(testStruct0)
    // testStruct1 爲實例
    StructToBytes<TestStruct1>(testStruct1)
複製代碼

在方法寫成泛型之後,不管結構體是什麼,函數只須要寫一遍。調用方只須要寫結構體的類型,和傳入相應的實例就能夠,而不須要寫多個函數。對於參數不同的而實現是同樣的函數,你們能夠考慮寫成泛型方法或者用接口。函數

由於泛型在多種面嚮對象語言中均有實現,爲了廣大水友能更好的理解,或者說消除語言方面的區別。接下來寫一個C#、JAVA、typescript的簡單泛型函數版本。ui

C#的泛型函數:spa

public void Test<T>(T params)
{
  // TODO    
}
// 調用實例1: Student爲類型,student爲傳入參數
Test<Student>(student);
// 調用實例2: String爲類型
Test<String>("我是參數")
// 調用實例3:Int爲類型
Test<Int>(100)
複製代碼

Java中沒有Struct,咱們將用簡單的例子:code

// 返回值爲T類型的實例
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}
複製代碼
// 調用
test1 obj1 = genericMethod(Class.forName("com.test.test1"));
test2 obj2 = genericMethod(Class.forName("com.test.test2"));
複製代碼

TypeScript 泛型函數代碼

function identity<T>(arg: T): T {
    return arg;
}
// 調用
let output0 Identity(3);
let output1 = identity("myString");
複製代碼

自我理解用法:泛型函數通常用在基礎類型的函數較多,像Int、String、struct,這種不能用接口限定的,用泛型去寫方法。若是是Object類型的話,能夠用接口是去限定參數。記得有一句話叫對接口編程,而不是對實現編程。

相關文章
相關標籤/搜索