zoukankan      html  css  js  c++  java
  • 泛型------《转载》

    泛型

    1, 什么是泛型?

           在理解泛型的定义之前,我们要明白非泛型的概念,非泛型就是大部分情况下是声明一个类,然后封装需要的行为,最后创建这些类的实例。

           泛型是一种更准确地使用有一种以上的类型的代码的方式。泛型允许我们声明类型参数化的代码,我们可以用不同的类型进行实例化。总结为一句话就是,泛型类型是类型的模板。

           请仔细理解下面两张图,或许能更好地理解泛型的原理。

    2, 泛型类?

           创建和使用常规的,非泛型的类的过程有两个步骤:声明类和创建类的实例。

           泛型的类不是实际的类,而是类的模板,所以我们必须先从它们构建实际的类类型, 然后个构建后的类类型的实例。

           下图演示了泛型类的创建过程:

    3, 声明泛型类?

           声明一个泛型类和声明普通类差不多,主要有如下区别:

    1>    在类名之后放置一组尖括号。

    2>    在尖括号中用逗号分隔的占位符字符串来表示希望提供的类型。这叫类型参数(Type Parameter)

    3>    在泛型类声明的主体中使用类型参数来表示应该被替代的类型。

    如下代码所示声明了一个SomeClass的泛型类:

    复制代码

     class SomeClass<T1, T2> //声明泛型类SomeClass,尖括号中是类型参数。

    {

    public T1 SomeVar = new T1(); //通常在这些位置使用类型。

    }

    复制代码

         注:泛型和非泛型区分的最主要的标志是:泛型类有尖括号。

    4, 创建构造类型?

           我们不能直接从泛型类型创建实例对象。首先,我们需要告诉编译器使用哪些真实类型来替代占位符(类型参数)。编译器获取这些真实类型并从它创建一个真实类型对象。

           创建构造类型例如:

    SomeClass<short,int> //尖括号中为类型实参

    5, 创建泛型类的变量和实例?

           创建泛型类实例一般有两种方法:

           方法一:和普通非泛型类的对象创建方法相似

    SomeClass<short, int> mySc1 = new SomeClass<short, int>(); //第一种方法创建泛型类实例。

          方法二:使用Var关键字隐式创建:

    var mySc2 = new SomeClass<short, int>(); //第二种方法,使用Var关键字创建。

          例如:

    复制代码

             class Program

    {

    static voidMain(string[] args)

    {

    var stackInt = new MyStack<int>(); //创建泛型类对象(或称实例),创建构造类型和创建实例可以一步完成。

    var stackString=new MyStack<String>();



    stackInt.Push(3); //调用方法

    stackInt.Push(5);

    stackInt.Push(7);

    stackInt.Print();



    stackString.Push("Generics are great!");

    stackString.Push("Hi there");

    stackString.Print();



    Console.ReadKey();

    }

    }

    class MyStack<T> //声明泛型类

    {

    T[] StackArray; //声明数组

    int StackPointer = 0; //声明并初始化整形变量。

    public void Push(T x) //定义无返回值方法

    {

    if (!IsStackFull)

    {

    StackArray[StackPointer++] = x; //为数组StackArray赋值。

    }

    }

    public T Pop() //定义有返回值方法

    {

    return (!IsStackEmpty) //条件运算符,可以用if...else...语句等价表示。

    ? StackArray[--StackPointer]

    : StackArray[0];

    }

    public MyStack() //构造函数初始化数组StackArray,为数组分配内存引用。

    {

    StackArray=new T[MaxStack];

    }

    public void Print() //构造函数

    {

    for (int i = StackPointer - 1; i >= 0; i--)

    {

    Console.WriteLine("Value:{0}",StackArray[i]);

    }

    }



    const int MaxStack = 10; //声明并初始化常量MaxStack

    bool IsStackFull //声明属性

    {

    get { return StackPointer >= MaxStack; }

    }

    bool IsStackEmpty //声明属性

    {

    get { return StackPointer <= 0; }

    }

    }

    复制代码

         程序输出结果为:

           附:泛型栈和非泛型栈之间的区别总结如下图表:

    非泛型

    泛型

    源代码大小

    更大:我们需要为每种类型进行一个新的实现。

    更小:不管构造类型的数量多少,我们只需要一个实现。

    可执行大小

    无论每一个版本的栈是否会被使用,都会在编译的版本中出现。

    可执行文件中只会出现有构造类型的类型。

    写的难易度

    易于书写

    比较难写

    维护的难易度

    更容易出问题,因为所有修改需要应用到每一个可用的类型上。

    易于维护,因为只需要修改一个地方。

    6, 泛型结构?

           例如:

    复制代码

           struct PieceOfData<T> //声明泛型结构

    {

    public PieceOfData(T value) //构造函数,初始化字段_Data。

    {

    _Data = value;

    }

    private T _Data;//声明私有字段(只能在类的内部访问)。

    public T Data //声明属性

    {

    get { return _Data; }

    set { _Data = value; }

    }

    }



    class Program

    {

    static voidMain()

    {

    var intData=new PieceOfData<int>(10);//创建构造类型实例

    var stringData=new PieceOfData<string>("Hi there!");



    Console.WriteLine("intData={0}",intData.Data);//访问属性

    Console.WriteLine("stringData={0}",stringData.Data);

    Console.ReadKey();

    }

    }

    复制代码

          程序输出结果为:

    7, 泛型接口?

           泛型接口的声明和非泛型接口的声明差不多,但是需要在接口名称之后的尖括号中有类型参数。

           例如:

    复制代码

        interface IMyIfc<T> //声明泛型接口,尖括号中为类型参数。

    {

    T ReturnIt(T inValue); //声明返回值类型为T的方法

    }



    class Simple<S> : IMyIfc<S> //声明泛型类,实现了泛型接口。

    {

    public S ReturnIt(S inValue) //实现接口成员方法。

    {

    return inValue;

    }

    }



    class Program

    {

    static voidMain(string[] args)

    {

    var trivInt = new Simple<int>(); //创建构造类型实例。尖括号中为类型实参。

    var trivString = new Simple<string>();



    Console.WriteLine("{0}",trivInt.ReturnIt(50)); //调用类对象实现的方法。

    Console.WriteLine("{0}",trivString.ReturnIt("Hi there!"));



    Console.ReadKey();

    }

    }

    复制代码

          程序输出结果为:

    8, 泛型委托?

    1>    要声明泛型委托,在委托名称之后,委托参数列表之前的尖括号中放类型参数列表。

    2>    注意,在这里泛型委托有两个参数列表:委托形参列表和类型参数列表。

    例如:

    复制代码

    delegate void MyDelegate<T>(T value); //声明泛型委托



    class Simple

    {

    public static void PrintString(string s) //方法匹配委托,

    {

    Console.WriteLine(s);

    }



    public static void PrintUpperString(string s)

    {

    Console.WriteLine("{0}", s.ToUpper());//调用string的ToUpper方法实现将字符串转换为大写。

    }

    }



    class Program

    {

    static voidMain(string[] args)

    {

    var MyDel = new MyDelegate<string>(Simple.PrintString); //创建委托的实例

    MyDel += Simple.PrintUpperString; //为委托添加方法。

    if (null != MyDel) //判断委托是否为空。

    {

    MyDel("VinceInfo");//调用委托。

    }

    else

    {

    Console.WriteLine("Delegate is empty!");

    }

    Console.ReadKey();

    }

    }

    复制代码

         程序输出结果如下:

    9, 泛型方法?

           泛型方法和泛型委托相似,有两个参数列表:

    1>    封闭在圆括号内的方法参数列表。

    2>    封闭在尖括号内的类型参数列表。

    例如:

    复制代码

    class Simple //非泛型类

    {

    static public void ReverseAndPrint<T>(T[] arr) //声明泛型方法

    {

    Array.Reverse(arr);

    foreach (T item in arr) //遍历数组。使用类型参数T。

    {

    Console.Write("{0}",item.ToString());

    Console.Write("");

    }

    Console.WriteLine(); //换行

    }

    }



    class Program

    {

    static voidMain(string[] args)

    {

    //创建三种类型的数组。

    var intArray = new int[] { 3,5,7,9,11};

    var stringArray = new string[] { "first","second","third"};

    var doubleArray = new double[] { 3.567,7.891,2.345};



    Simple.ReverseAndPrint<int>(intArray); //调用泛型方法,显示调用

    Simple.ReverseAndPrint(intArray); //使用推断类型隐式调用。



    Simple.ReverseAndPrint<string>(stringArray);

    Simple.ReverseAndPrint(stringArray);



    Simple.ReverseAndPrint<double>(doubleArray);

    Simple.ReverseAndPrint(doubleArray);



    Console.ReadKey();



    }

    }

    复制代码

    程序输出结果为:

    10,扩展方法和泛型类?

           扩展方法可以和泛型类结合使用,它允许我们将类中的静态方法关联到不同的泛型类上,还允许我们像调用类构造实例的实例方法一样来调用方法。

           例如:

    复制代码

           static class ExtendHolder

    {

    public static void Print<T>(this Holder<T> h) //声明扩展方法并关联到泛型类Holder<T>上。

    {

    T[] vals = h.GetValues(); //调用泛型类的方法。

    Console.WriteLine("{0}, {1}, {2}",vals[0],vals[1],vals[2]); //" "转义符

    }

    }



    class Holder<T> //声明泛型类

    {

    T[] vals=new T[3];//声明并初始化数组。

    public Holder(T v0, T v1, T v2) //构造函数,为数组赋值。

    {

    vals[0] = v0;

    vals[1] = v1;

    vals[2] = v2;

    }

    public T[] GetValues() //声明方法,返回数组类型。

    {

    return vals;

    }

    }



    class Program

    {

    static voidMain(string[] args)

    {

    var intHolder = new Holder<int>(3,5,7); //创建泛型类实例

    var stringHolder = new Holder<string>("a1","b2","c3");



    intHolder.Print(); //调用方法

    stringHolder.Print();



    Console.ReadKey();

    }

    }

    复制代码

         程序输出结果为:

          关于泛型先写到这里,欢迎大家指正,谢谢!

  • 相关阅读:
    jython resources
    Installing a Library of Jython ScriptsPart of the WebSphere Application Server v7.x Administration Series Series
    jython好资料
    ulipad install on 64bit win7 has issue
    an oracle article in high level to descibe how to archtichre operator JAVA relevet project
    table的宽度,单元格内换行问题
    Linux常用命令大全
    dedecms系统后台登陆提示用户名密码不存在
    登录织梦后台提示用户名不存在的解决方法介绍
    Shell常用命令整理
  • 原文地址:https://www.cnblogs.com/bedfly/p/11898944.html
Copyright © 2011-2022 走看看