Unity游戏开发学习C#基础 之 类(Class)

一.类(Class)

1. 定义:类是一种数据类型的蓝图,它规定了在这个对象上可以执行什么操作。

2. 实例化:类不能直接使用,必须先实例化后才能使用,实例化就是一个创建对象的过程。C#使用new关键字来实例化对象。

  • 个人理解:类就是一种概念,当这个概念被实现的时候,它就是一个有实体的类,就是对象。

3. 静态(static):一种数据类型的约束

  • 静态成员可以是成员变量也可以是成员函数
  • 静态成员不可以通过对象调用,只能通过类来调用
  • 个人理解:因为被修饰为静态后就是这个类的唯一,这个类只有这一个变量或者函数,所以的对象都公用这个。

4. 构造函数和析构函数

  • 构造函数: 访问修饰符 类名(如果没有构造函数会默认生成无参数的空构造函数)
  • 析构函数:~类名

5. 访问修饰符(指是否能够访问(找)的到)

  • Public:任何公用成员可以被外部类访问。
  • Private:只有同一个类的函数可以访问它的私有成员。
  • Protected:该类内部和继承类中可以访问。
  • internal:同一个程序集的对象可以访问。(同一个命名空间内)
  • Protected internal:3和4的并集,符合任意一条都可以访问
  • 范围比较
private < internal/protected < protected internal < public

6. 命名空间(static):一种数据类型的约束

namespace 命名空间名字{
    
    
	class c1{
    
     fucton1(){
    
    } }
}
class c1{
    
     fucton1(){
    
    } }
//调用
命名空间名字.c1.fucton1()		//调用第一个函数
c1.fucton1()					//调用第二个函数

同一个命名空间内不能重名,没有写在命名空间内的默认是全局的,在命名空间内的类要引入命名空间再调用

7. 面向对象

  1. 继承

    • 一个类可以获得另一个类的全部(数据成员和成员函数)就是类的继承。
    • 这个已有的类(被继承的类)被称为的基类,这个新的类(继承基类的类)被称为派生类。
    • 继承就是将公用的属性或方法抽离到父类的过程。这个思维称之为面向对象
    • 子类不可以访问父类中的Private的变量(感觉上继承是像里面又多了一个类,继承来的不完全是自己的)。
  2. 封装

    • “把一个或多个项目封闭在一个物理的或逻辑的包中”,通俗一点的解释就是,隐藏技术细节,仅暴露外部调用者关心的接口

    • virtual 是虚拟的含义,表示这些成员将会在继承后从写其中的内容,但virtual不能修饰使用static修饰的成员

      //修饰属性
      访问修饰符 virtual  数据类型  属性名
      
      //修饰方法
      访问修饰符  virtual  返回值类型 方法名 {
              
              }
      
    • override,是在子类中重写父类中的方法,两个函数的函数特征(函数名、参数类型与个数)相同。用于扩展或修改继承的方法、属性、索引器或事件的抽象或虚拟实现。提供从基类继承的成员的新实现,而通过override声明重写的方法称为基方法。

      //修饰方法
      基方法的访问修饰符  override 基方法的返回值类型 基方法的方法名 {
              
              }
      
  3. 多态

    • 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。(因为函数被重载重写等原因)
    • 多态就是同一个接口使用不同的实例而执行不同操作。
    • 静态多态(编译时编译器能确定的)
      -比如说 派生类经过重写基类的方法后在对应的对象中调用该方法。会根据容器来确定方法的内容。
    • 动态多态(运行时多态,只有运行时才能确定的方法)
      -比如说 一个基类有多个派生类但是每个派生类都重写了基类的方法,用基类才存放派生类的对象(只可以子类赋值给父类不可以反过来),然后调用该方法,会根据容器来确定方法的内容。

8. 覆盖和重载

  • 覆盖:发生在 继承关系中,通过virtualoverride两个关键字来实现。(函数名已经函数参数是一模一样的) ,即可实现覆盖。
  • 重载:发生在 任何关系中,只要保证函数名称一致,函数参数不一致(带参数和不太参数,带参数顺序不一致,带参数个数不一致),即可实现重载。

9. this和base

  • this:指的是访问当前类的成员
  • base:指的是访问基类的成员

10. 只读变量和常量

  • const:在类内声明的const常量

    • 外部访问时,必须通过类名进行访问,但不可修改值
    • 只能在声明时初始化,不允许在任何其他地方对其初始化(包括构造函数)
    • 在某种程度,被const修饰的变量(常量),不可变值
  • readonly:在类内声明的readonly常量

    • readonly const ,不可以共同修饰一个类型(基本数据类型+自定义数据类型)
    • readonly修饰的类型,只能被类的实例化进行访问,但不可修改值
    • readonly的初始化,只能发生在构造函数或者声明中
  • 可以通过访问修饰符构成的语法块,来实现类似外部只读的效果 get set

    //public修饰get private修饰set
    public int value1 {
          
          get;private set;}
    
  • value赋值

    //把值放在另一个变量里面 不知道为什么要这样写
    public int value1;
    public int value2
    {
          
          
    	get{
          
           return value1; }
    	set{
          
           value1 = value; }
    }
    

11. 静态类

  • 类可以声明为static,这将变成一个静态类,不得被继承,特点是仅包含静态成员或常量。

  • 静态类的特点:

    • 不能被实例化,意味着不能使用 new 关键字创建静态类实例。

    • 仅包含静态成员或常量,内部成员必须是静态成员/常量

    • 不能被继承,无法作为基类派生

    • 静态类不允许有实例构造函数,只允许纯在一个静态构造函数,(静态类的静态构造函数,经测试发现,并不会执行)

    • 静态构造函数:

      • 静态构造函数不需要增加访问修饰符(因为是被系统调用的,不让加修饰符)
      • 静态构造函数无论多少实例都只被调用一次,而且是只被系统自动调用一次
  • 静态类一般用于工具类

12. 抽象类

  • 类可以声明为abstract,这将变成一个抽象类。

  • 抽象类的特点:

    • 不能被实例化,意味着不能使用 new 关键字创建实例。
    • 可只提供部分函数实现,也可仅声明抽象函数。
    • 支持构造函数,静态构造函数和普通构造函数
    • 静态构造函数只执行一次,但是其他构造函数则根据不同实例,分别再次调用。
    • 允许 virtual 虚函数 和 override 重写
    • 若函数声明为 abstract,则不允许包含函数体; 子类必须实现父类的该方法。
  • 抽象类是提炼出了一些类共有的属性或函数接口的组织,为子类提供设计思想,配合多态多用于代码架构设计。

13. 密封类

  • 类可以声明为sealed,这将变成一个密封类。

  • 密封类的特点:

    • 不能被继承,但可以继承别的类或接口;
    • 密封类不能声明为抽象类既 sealed abstract不能共存
    • 密封类内的函数,不允许增加sealed关键字
    • 密封类可以正常继承常见类(普通类、抽象类)、接口
  • 密封类一般用于防止重写某些类或接口影响功能的稳定

14. 泛型类

  • 类名后面可以添加 <T1、T2、T3…>,这将变成一个泛型类。泛型 T1、T2、T3可以通过 where关键字来限定类型。

  • 泛型类的特点:

    • 在声明时可以不指定具体类型,但是在 new实例化时必须指定T类型
    • 可指定泛型类型约束
    • 如果子类也是泛型的,那么继承的时候可以不指定具体类型
  • 泛型约束注意的点 .NET含有以下五种泛型约束:

    • where T : class T必须是一个类
    • where T : struct T必须是一个结构类型
    • where T : new() T必须要有一个无参数的构造函数
    • where T : NameOfBaseClass T必须继承名为NameOfBaseClass的类
    • where T : NameOfInterface T必须实现名为NameOfInterface
  • 例子:

    //定义   普通
    public class Class1<T>{
          
           private T[] array; }
    //调用
    Class1<int> myClass = new Class1<int>();
    
    //定义  泛型可以是自定义的类
    public class ClassType {
          
           public int a; }
    public class Class2<T>{
          
          } 
    //public class Class2<T> where T:ClassType {}   //用约束
    //调用
    Class2<ClassType> myClass = new Class2<ClassType>();
    
    //定义   多个泛型
    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> {
          
          }
    //定义   子类可以有父类没有的泛型
    public class Son<X,Y> :BaseParent<int,string> {
          
          }
    
    //定义   方法泛型   方法泛型的作用于仅限于方法内 类的则是整个类里面
    public class Son:BaseParent<int,string>
    {
          
          
    	public void Show<X>( X A ) {
          
          ...}
    }
    //调用
    Son son = new Son();
    son.Show<string>("show your text");
    
  • 泛型类一般用于处理一组功能一样,仅类型不同的任务时

14. 接口

  • interface + name 这将变成一个接口

  • 接口的特点:

    • 接口值声明接口函数,不包含实现
    • 接口函数访问修饰符必须是public,不能将函数的声明改为私有的
    • 接口成员函数的定义是派生类的责任,接口只提供派生类应遵循的标准结构
    • 接口不可以被实例化,既不可new
    • 接口可以继承其他接口,允许单一继承也允许多重继承(类只允许继承单个类,但是可以同时继承多个接口,只要实现了接口的函数就行)
  • 约束一些行为规范时,可以用接口

15. 接口和抽象类之间的区别

  • 共同点:

    • 都可以被继承,但是不可以被实例化
    • 都支持只声明函数,不包含实现(抽象类函数不加修饰符可以包含实现)
    • 派生类必须实现未实现的方法
  • 不同点:

抽象类 接口
变量 可以声明变量 不允许声明变量
构造函数 不允许构建函数 允许拥有构造函数
函数实现 函数不是抽象的情况下可以实现 不可以实现
访问修饰符 默认是private函数前面若是abstract那访问修饰符也不能是private ; 但是非abstract声明的函数是允许private 或者 protected 默认是public 不允许改变为private
是否多重继承 抽象类只能被单一继承 接口可被多重继承
性质 抽象类是一个不完整的类,需要进一步细化 接口是一个行为规范
作用 抽象类更多的是定义一系列紧密相关的类间 接口大多数是关系疏松但都实现某一功能的类中

16. struct 结构体

  • struct + name { ... } 便声明了一个结构体

  • 结构体是值类型数据结构,它使得一个单一变量可以存储各种数据类型的相关数据。

  • 结构体的特点:

    • 结构体可带有方法、字段、索引、属性、运算符方法和事件
    • 结构体可定义构造函数,但不能定义析构函数。不能定义无参构造函数,无参构造函数是自动定义的,且不能被改变
    • 与类不同,结构不能继承其他的结构和类,但是可实现一个或多个接口。
    • 结构不能作为其他结构或类的基础结构。
    • 结构成员不能指定为abstract、virtual 或 protected
    • 结构体不能通过 new 来实现

17. struct 和 class 的异同

  • 相同点:

    • 都支持静态构造函数
    • 都支持自定义函数
    • 结构体和类对于const修饰的变量的使用方法是一样的
    • 结构体变量和类对象必须进行初始化才可以访问函数
  • 不同点:

struct class
构造函数 结构体不允许定义无参构造函数,只允许定义有参构造函数 类是都可以
析构函数 不允许定义析构函数 类是可以的
函数的修饰符 结构体函数不允许声明为 virtual虚函数;结构体函数不允许声明为protected受保护的函数 类是可以的
类型修饰符 结构体类型不允许声明为abstract 类是可以的
关于变量-普通变量 结构体声明的全局普通变量(不带修饰符的),不能在声明时直接赋值,只能在构造函数里面赋值 类是哪里都可以的
关于变量-readonly 结构体声明的全局readonly变量,只能在构造函数里面赋值 类是哪里都可以的
关于继承 结构体之间不可以互相继承 类与类之间是可以继承的(sealed密封类除外)
访问变量 结构体访问成员变量,给变量赋值,就可直接访问 类必须实例化对象才可以访问
new 结构体属于值类型,结构体的new并不会在堆上分配内存,仅仅是调用结构体的构造函数初始化而已 类属于引用类型,类的new会在堆上分配内容,而且也会调用类的构造函数进行初始化

猜你喜欢

转载自blog.csdn.net/anxious333/article/details/125903283