泛型函數(shù)

泛型,即“參數(shù)化類型”。一提到參數(shù),最熟悉的就是定義方法時有形參,然后調(diào)用此方法時傳遞實參。那么參數(shù)化類型怎么理解呢?顧名思義,就是將類型由原來的具體的類型參數(shù)化,類似于方法中的變量參數(shù),此時類型也定義成參數(shù)形式(可以稱之為類型形參),然后在使用/調(diào)用時傳入具體的類型。——來自百度

自我理解:泛型函數(shù)就是,你定義函數(shù)時候,是萬能類型。在調(diào)用的時候,只要你把具體的類型傳進(jìn)去就好。好處呢,就是代碼的復(fù)用,減少代碼量。

在面向?qū)ο蟮恼Z言中都是有泛型的這個概念和實現(xiàn)的。比如說:JAVA、C#、C++、TypeScript等等。但是我們在看書或者學(xué)習(xí)的時候呢,一般只是看到了這樣的概念,或者說例子很簡單,就是一個Int 和 string 參數(shù)的泛型使用。

其實泛型是用的很廣泛的,特別是在寫底層框架的時候。當(dāng)大家去看源碼的時候,會看到很多泛型。最近的工作中也用到了泛型,算是寫底層吧,因為給別人調(diào)用。

工作需求是這樣的 ,使用TCP/IP協(xié)議,從客戶端發(fā)送 “結(jié)構(gòu)體”到服務(wù)端。一般都是會將數(shù)據(jù)轉(zhuǎn)化成byte[],再進(jìn)行數(shù)據(jù)的傳送。查資料和用泛型改造后:

C#代碼

// 結(jié)構(gòu)體轉(zhuǎn)byte數(shù)組
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);
    }
}
    
// 結(jié)構(gòu)體轉(zhuǎn)byte數(shù)組
public static T BytesToStruct<T>(byte[] arr) where T : new()
{
    // where后面的泛型約束:參數(shù)需要有一個無參的構(gòu)造函數(shù)
    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)

在方法寫成泛型以后,無論結(jié)構(gòu)體是什么,函數(shù)只需要寫一遍。調(diào)用方只需要寫結(jié)構(gòu)體的類型,和傳入相應(yīng)的實例就可以,而不需要寫多個函數(shù)。對于參數(shù)不一樣的而實現(xiàn)是一樣的函數(shù),大家可以考慮寫成泛型方法或者用接口。

因為泛型在多種面向?qū)ο笳Z言中均有實現(xiàn),為了廣大水友能更好的理解,或者說消除語言方面的區(qū)別。接下來寫一個C#、JAVA、typescript的簡單泛型函數(shù)版本。

C#的泛型函數(shù):

public void Test<T>(T params)
{
  // TODO    
}
// 調(diào)用實例1: Student為類型,student為傳入?yún)?shù)
Test<Student>(student);
// 調(diào)用實例2: String為類型
Test<String>("我是參數(shù)")
// 調(diào)用實例3:Int為類型
Test<Int>(100)

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

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

TypeScript 泛型函數(shù)代碼

function identity<T>(arg: T): T {
    return arg;
}
// 調(diào)用
let output0 Identity(3);
let output1 = identity("myString");

自我理解用法:泛型函數(shù)一般用在基礎(chǔ)類型的函數(shù)較多,像Int、String、struct,這種不能用接口限定的,用泛型去寫方法。如果是Object類型的話,可以用接口是去限定參數(shù)。記得有一句話叫對接口編程,而不是對實現(xiàn)編程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容