上一部分讲解了类(如何创建类,类的实例化等)以及一些基于类上的基本操作,比如继承,多态,封装,重载和重写(覆盖),这一部分,我们将细分化的介绍类的更多表现形式。

一、静态类

就像我们上一部分说的那样,我们在类内使用static声明的变量,称为类的静态成员变量,这样的函数称为类的静态成员函数。

为什么我们要用静态类呢?一般当这个类很频繁被调用,定义成静态的就不用每次给他实例化了,直接用类去调用可以了,像工具类一般都定义成静态的,这样不用每次实例化了,直接用类名去调用(普通类调用时,必须先要给他new 下,才能去调用)

特点:(1)不能被实例化、不能被继承

(2)不能包含实例构造函数,但是可以包含一个静态构造函数,且静态构造函数不可被调用

1:静态修饰符

const:在类内声明的const常量,在类外访问时,只能通过类名进行访问(不可通过实例化类名)

MyClass myClass= new Myclass();
int a = MyClass.mVaule    而不可为myClass.mVaule

在类内声明的const常量,只能在声明时进行初始化,不允许任何其他地方对其初始化

public const int mVaule1=10;

在某种程度,被const修饰的常量,不可变值

readonly:在类内声明的readonly,不可与const共同修饰一个数据类型

public readonly const int mVaule;   //这样的声明方式不允许

readonly修饰的类型,可以被类的实例进行访问,但不可修改值。

readonly的初始化,只能发生在构造函数或声明中。

2:静态构造函数

①静态构造函数,不需要增加访问修饰符

②静态构造函数,无论多少实例,都只被调用一次,而且都只是被系统自动调用一次。

public class Class3;
{static Class4(){Debug.Log("Father");}
}public class Class4: Class3
{public Class3(){Debug.Log("Son");}}public calss ClassTest:MonoBehaviour
{void Start(){Class3 iClass1 =new Class3();Class3 iClass2 =new Class3();}
}

如上代码,父类声明了静态构造函数,在输出时,只输出一次Father,而输出两Son。

3:静态类

①:静态类不允许有实例构造函数,只允许存在一个静态构造函数

②:不能被实例化

③:静态类内部成员,必须是静态成员,函数也必须是静态成员函数

public static class Myclass
{public const int mVaule=10;   //可以添加静态修饰符public static int mVaule;    //成员必须是静态public static void Show(){}  //函数必须是静态
}

④:静态类无法被继承

二、抽象类

可以在类前加static,使之成为抽象类,它一般是为子类提供设计思想,配合多态用于代码的架构设计。

特点:

不能被实例化

抽象类可以继承抽象类

支持构造函数,静态构造函数只执行一次;其他构造函数会根据实例不同,分别再次调用

允许virtual虚函数

抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类,但抽象函数不允许有函数体,且必须显示覆盖父类的该方法。

public abstract class MyClass6
{public MyClass6(){Debug.Log("MyClass6默认构造函数");}static MyClass6(){Debug.Log("MyClass6静态构造函数"); //静态构造函数只执行一次}public void Show1()                    //普通构造函数会根据实例多次调用{Debug.Log("普通Show1");}public virtual void Show2()   //可以使用virtual{Debug.Log("Myclass6 virtual Show2");}public abstract void Show3();  //定义抽象方法,不允许有函数体,且在实现时候必须使用覆盖}
public class MyClass7:MyClass6      //抽象类可以继承
{public MyClass7(){Debug.Log("MyClass7");}public override void Show2()    //Show2的重写{Debug.Log("MyClass7 override Show2");}public override void Show3()    //Show3抽象过了,想实现也必须重写{}
}public class Abstract : MonoBehaviour
{void Start(){Myclass7 myClass7=new Myclass7();Myclass7 myClass8=new Myclass7();}

如上的输出结果,则只输出一次静态构造函数

三、密封类(接口)

密封类一般用于防止重写某些类或接口影响功能的稳定,在class前加sealed,变为密封类。

特点:不能被继承,但可以继承别的类或者接口

抽象abstruct和sealed不能共存

密封类内的成员函数,不得声明成sealed

public sealed class MyClass8
{}public class MyClass9:MyClass8 //不允许被继承{}public class Myclass9
{public sealed class Myclass10:Myclass9 //允许继承其他类{}
}

四、泛型类&泛型方法

我们在处理一组功能相同,仅类型不同的任务的时候,可以在类名后添加<T1,T2,T3..>,将变成一个泛型类,泛型T1,T2,T3,可以通过where关键字来限定类型。

特点:

在声明时可以不指定具体的类型,但是new实例化时必须指定T类型

可指定泛型类型约束

如果子类也是泛型的,那么继承的时候可以不指定具体类型

1:泛型类的效率

#需求:在类内定义一个数组,让这个类具备设置数据和访问数据的能力

①:不使用泛型类

我们必须分别创建两个类,分别用来存储int类型和string类型的数组

public class MyClass               //创建一个类用来存储int类型的数组
{private int[]m_array;   //声明了私有Int类型的数组m_arraypublic MyClass(int size) //构造函数,设置容量{m_array=new int[size];}public void Set(int index,int value) //设置数据的方法,int类型的下标和数据{m_array[index]=value;  }public int Get(int index)    //设置了访问数据的方法{return m_array[index];      //返回Index   }public class MyClass1              //创建一个类用来存储string类型的数组
{private string[]m_array;   //声明了私有string类型的数组m_arraypublic MyClass1(string size) //构造函数,设置容量{m_array=new string[size];}public void Set(int index,string value) //设置数据的方法,string类型的下标和数据{m_array[index]=value;  }public string Get(int index)    //设置了访问数据的方法{return m_array[index];      //返回Index   }}public class Tclass
void Start()
{MyClass myClass= new MyClass(5);  //实例化后设置容量myClass.Set(0,1);                 //设置数据myClass.Set(1,2);int a=myClass.Get(0);int a=myClass.Get(1);Debug.LogFormat("第(0)号位,值:{1}",0,a);Debug.LogFormat("第(1)号位,值:{1}",1,b);
}

②使用泛型

public class MyClass<T>               //创建一个泛型类,表示方法如图
{private T[]m_array;   //声明了私有T类型的数组m_arraypublic MyClass(int size) //构造函数,设置容量{m_array=new T[size];           //构造函数也使用T类型}public void Set(int index,T value) //设置数据的方法,T类型的下标和数据{m_array[index]=value;  }public T Get(int index)    //设置了访问数据的方法{return m_array[index];      //返回Index   }public class Tclass
void Start
{                            //在原本T的位置可以改成string,这样就可以存储string类型的数据了
MyClass<string> myClass = new MyClass<string>(5);
myClass.Set(0,"1");
myClass.Set(1,"2");
string a =myClass.Get(0);
string b =myClass.Get(1);
Debug.LogFormat("第(0)号位,值:{1}",0,a):
Debug.LogFormat("第(1)号位,值:{1}",0,b):
}

2:存储类的数据类型

①:不使用where限定

public calss MyClassType      //创建需要被存储的类
{public int a;public MyClassType(int value)  //创建类的成员{this.a=value;}
}public class MyClass<T>
{private T[]m_array;   public MyClass(int size) {m_array=new T[size];        }public void Set(int index,T value){m_array[index]=value;  }public T Get(int index)  {return m_array[index];   }void Start()
{MyClass<MyClassType>  myClass =new MyClass<MyClassType>(5);  //在实例化的时候也需要改变类型myClass.Set(0,new MyClassType(1));myClass.Set(1,new MyClassType(2));MyClassType a=myClass.Get(0);MyClassType b=myClass.Get(1);Debug.LogFormate("第(0)号位,值:{1},",0,a,a);Debug.LogFormate("第(1)号位,值:{1},",1,b,a);
}

②使用where限定

public calss MyClassType      //创建需要被存储的类
{public int a;public MyClassType(int value)  //创建类的成员{this.a=value;}
}public class MyClass<T> where T:MyClassType   //使用where来限定T的类型
{private T[]m_array;   public MyClass(int size) {m_array=new T[size];        }public void Set(int index,T value){m_array[index]=value;  }public int Get(int index)  //此处直接修改被存储类的类内定义的成员类型{return m_array[index].a;   }void Start()
{MyClass<MyClassType>  myClass =new MyClass<MyClassType>(5);  //在实例化的时候也需要改变类型myClass.Set(0,new MyClassType(1));myClass.Set(1,new MyClassType(2));int a=myClass.Get(0);                      //直接使用int访问即可int b=myClass.Get(1);Debug.LogFormate("第(0)号位,值:{1},",0,a);Debug.LogFormate("第(1)号位,值:{1},",1,b);
}

NET含有以下五种泛型约束:

1:where T:class|T 必须是一个类

2:where T:struct|T 必须是一个结构类型

3:where T:new()|T 必须要有一个无参数的构造函数

4:where T:NameOfBaseClass |T 必须继承名为NameOfBaseClass的类

5:where T:NameOfInterface |T 必须实现名为NameOfInterface的接口

3:泛型方法

public void Show<X>(X A)    //这里的X代表使用泛型的类型,A代表你创建的类型的名称
{Debug.Log("A="+A);
}void Start()
{Son son= new Son();son.Show<string>("string");  //在外部调用的时候会自动显示需要的类型,后方括号内可写名称
}

4:泛型在继承中的使用,子类给父类限定方法

public class BaseParent<T,X>      //父类,赋值类型来自子类
{}
public class Son<T,X>:BaseParent<T,X>   //在定义类的时候不指定类型
{}public class Son:BaseParent<int,string>   //在定义类的时候指定父类的类型
{}
public class Son<T,X,Y,A>:BaseParent<T,X>   //父类延迟赋值的同时,给自己增加了类型Y,A
{}

五、接口

接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因

此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。

可以使用interface+name,就形成了一个接口。

下面这位博主讲的更为详细。

JAVA基础——接口(全网最详细教程)_刘扬俊的博客-CSDN博客_java接口

特点:

接口只声明接口函数,不包含实现

接口函数访问修饰符,必须是public,默认也是public

接口成员函数的定义时派生类的责任,接口提供了派生类应遵循的标准接口

接口不可被实例化

接口可以继承其他接口,接口允许多重继承

1:接口的具体代码实现

public interface BaseInterface1    //接口的引入,interface +name
{void ShowWindow();              //接口可声明函数void HideWindow();!!!    void Show1()               //接口不可包含函数体{!!!    }!!!     private void Show3();      //不能将函数的声明改为私有的
}public interface BaseInterface2
{void PlaySound();void CloseSound();
}
public interface MyInterface:BaseInterface1,BaseInterface2   //接口允许单一继承,也允许多重继承{}
public class MyClass16
{}
public class Tinterface : MonoBehaviour
{void Start(){!!!  BaseInterface inter =new BaseInterface();   //接口不可以被实例化}

2:接口和抽象类的区别和共同点

①:区别

接口不允许声明变量;而抽象类可以

public interface Myinterface
{public int a;                     不可!!!
}public abstract calss MyAbstract
{public int b;
}

接口不允许有构造函数(普通和静态),而抽象类可以

public interface Myinterface
{Myinterface();static Myinterface();                  不可!!!
}public abstract calss MyAbstract
{MyAbstract();static MyAbstract();
}

接口不允许函数实现,而抽象类可以

接口允许多重继承,而抽象类不可以多重继承

{接口默认的访问修饰符是public,不允许改为private

抽象类默认的访问修饰符是private,函数前面若是abstract,那访问修饰符也不能是private,但是非abstract声明的函数允许private,protected. }

②:共同点

两者都不允许实例化

函数都支持只声明,不实现

他们的派生类都必须去实现接口或抽象类的方法

public interface MyInterface
{void Show1();
}public abstract MyAbstract
{void Show2();
}public class MyClass:Myinterface
{public void ShowInterface()   //实现interface中的方法{}
}
public class MyClass:MyAbstract
{public override void ShowAbstract()  //实现abstract中的方法{}
}

六、结构体Struct

结构体是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。它使得一个单一变量可以存储各种类型的相关数据,我们使用Struct+name结构来声明一个结构体。

特点:

结构体可以带方法,字段,索引,属性,运算符,方法和事件

结构体可以定义构造函数,但不能定义析构函数,无参构造函数(自动定义,且不可改变)

结构体不能继承其他的结构体或类,但可以实现一个或多个接口

结构体不能作为其他结构或类的基础结构

结构成员不能指定为abstract、virtual、protected

结构体不能实例化

1:struct和class的异同

①相同点:

都支持静态构造函数、自定义函数

struct MyStruct
{Static MyStruct(){}public void Show(){}
}class MyClass
{Static MyClass(){}public void Show(){}
}

结构体和类对于const修饰的变量的使用方式是一样的

访问函数时,结构体和类都必须进行初始化才能访问

MyClass myClass = new MyClass();
myClass.Show();MyStruct myStruct = new MyStruct();
myStruct.Show();

②不同点:

结构体不允许定义无参构造函数,只允许定义有参构造函数,但类都可以

struct MyStruct
{public MyStruct(int value){}public MyStruct()            !!!不可{}
}

结构体不允许定义析构函数,类可以

结构体不允许声明为virtual,但类可以

struct MyStruct
{public virtual void Show2(){}     !!!不可
}

结构体不允许声明为abstratct ,但类可以

结构体不允许声明protected,但类可以

结构体声明的全局普通变量(不带修饰符),不能在声明时直接赋值,只能在构造函数里赋值,但类哪里都可以

struct MyStruct
{public int a;public MyStruct(int value){a=value}
}class MyClass
{public int a=2000;
}

结构体声明的全局readonly变量,只能在构造函数里赋值,而类都可以

struct MyStruct
public readonly string str;
public MyStruct(int value)                             //只能在有参构造函数赋值
{a=value;str="20";
}class MyClass
public readonly string str="20";                        //直接赋值
或
public read only string str;
public MyClass(int value){str="20"}                    //构造函数赋值

结构体之间不能相互继承,但是类与类可以

结构体访问成员变量,给变量显示赋值可直接访问,而类必须实例化后才可访问

结构体如果不通过new初始化,是不可以直接访问内部变量(const除外)

MyStruct myStruct;
myStruct.a=2000;
int b =myStruct.a;MyClass myClass = new MyClass();
int a =myClass.a;

结构体的new并不会在堆上分配内存,仅是调用结构体的构造函数初始化而已

类的new会在堆上分配内存,而且也会调用类的构造函数进行初始化

零基础自学C#——Part4:类的表现形式相关推荐

  1. 零基础自学应用近世代数 第1章 引言和预备知识 1.1 几类实际问题 1.1.1 一些计数问题

    零基础自学应用近世代数 文章目录 零基础自学应用近世代数 第1章 引言和预备知识 1.1 几类实际问题 1.1.1 一些计数问题 [1]项链问题 [2]分子结构的计数问题 [3]正多面体着色问题 [4 ...

  2. 零基础学python用什么书-零基础自学python3 好用的入门书籍推荐

    零基础自学python3 好用的入门书籍推荐,博学谷小班整理了六本数,推荐阅读 <Python for data analysis>.<Python数据分析与挖掘实战>.< ...

  3. python3入门书籍-零基础自学python3 好用的入门书籍推荐

    零基础自学python3 好用的入门书籍推荐,博学谷小班整理了六本数,推荐阅读 <Python for data analysis>.<Python数据分析与挖掘实战>.< ...

  4. 自学python需要多长时间-零基础自学python要多久?

    原标题:零基础自学python要多久? 如果是自学,从零基础开始学习Python的话,依照每个人理解能力的不同,大致上需要一年半左右的时间,至于能不能学好要看你自己的领悟了,至于找到工作那就不好说了. ...

  5. 零基础学python用哪本书好-零基础自学python3 好用的入门书籍推荐

    零基础自学python3 好用的入门书籍推荐,博学谷小班整理了六本数,推荐阅读 <Python for data analysis>.<Python数据分析与挖掘实战>.< ...

  6. 0基础学python要多久-零基础自学python要多久?

    原标题:零基础自学python要多久? 如果是自学,从零基础开始学习Python的话,依照每个人理解能力的不同,大致上需要一年半左右的时间,至于能不能学好要看你自己的领悟了,至于找到工作那就不好说了. ...

  7. 零基础自学UI设计要看什么书籍和资料

    本文由:"学设计上兔课网"原创,图片素材来自网络,仅供学习分享 零基础自学UI设计要看什么书籍和资料?学习UI设计的方法有很多,有些会选择报名UI设计培训班学习,也有的小伙伴会选择 ...

  8. 零基础自学平面设计需要学些什么?

    作为一个新手从零基础开始学习平面设计,首先明白的是平面设计是什么,当你能够自己解释平面设计,让你身边的人明白的时候,基本你就是开始入门了. 同时你还要明白的,学习平面设计需要掌握哪些基本知识,和行业性 ...

  9. 非零基础自学Golang 第1章 走进Go 1.2 Go语言官方文档 1.3 学好Go 的建议

    非零基础自学Golang 文章目录 非零基础自学Golang 第1章 走进Go 1.2 Go语言官方文档 1.3 学好Go 的建议 1.3.1 了解语言特性及自身需求 1.3.2 动手写代码 1.3. ...

最新文章

  1. gitkraen_超详细!Github团队协作教程(Gitkraken版)
  2. SpringCloud:Hystrix 熔断机制(基本配置、服务降级、HystrixDashboard服务监控、Turbine聚合监控)
  3. Ubuntu开发环境搭建
  4. JAVA岗位比嵌入式岗位_java嵌入式职业选择?
  5. 情人节,怎么同时约会女神和女朋友
  6. android 系统(8)---Android 学习网站汇总
  7. oracle密码重用,关于Oracle 9i数据库密码重用规则分析
  8. C语言的常用字符串操作函数(一)
  9. js获取可视区域高度
  10. 关于返回一个整数数组中最大子数组的和的问题(续01)
  11. 和浏览器并发请求数有关的一些前端技术
  12. 常见面试题汇总 —— C语言
  13. thinkpad s5黑将摄像头最新驱动_第一款以iOS方式运行的安卓手机:联想新机S5黑科技震撼来袭!...
  14. 在线工具 将图片透明化
  15. ios应用中调用系统电话、浏览器、地图、邮件等 以及打开其他应用(如qq,msn)
  16. 针式 PKM 个人知识管理软件 帮助
  17. proxmox VE开NAT小鸡 无法联网,怎么开NAT模式
  18. c语言静态检测工具,静态代码检测工具---PC-lint(for c/c )
  19. K-Means算法实现网页聚类
  20. 2022元宇宙十大商业魔咒

热门文章

  1. [转]触乐独家:揭秘愈演愈烈的苹果“做号退款”生态圈
  2. 【CSS】固定区域竖向滚动
  3. 手把手教你制作docSet文档(用于Dash或zeal)
  4. centos8 修改root密码
  5. aspose-words破解版使用java版
  6. HDU 2448 Mining Station on the Sea(Floyd+最优匹配)
  7. 程序员如何修炼项目管理能力?
  8. GIT TAG 批量删除
  9. ELK日志分析平台(一)—elasticsearch安装及配置、elasticsearch图形化插件安装
  10. JAVA判断是否是水仙花数