# 类和对象 所谓面向对象是指在编程时将任何事物都看成是一个对象来描述。 对象包括属性和方法,属性是指对象固有的特征,方法则是对象的行为。 面向对象语言的三大特征分别是封装、继承、多态。 ## 类 类定义的具体语法形式如下。 ```C# 类的访问修饰符 修饰符 类名 { 类的成员 } ``` 其中: - 类的访问修饰符:用于设定对类的访问限制,包括 public、internal 或者不写,用 internal 或者不写时代表只能在当前项目中访问类;public 则代表可以在任何项目中访问类。 - 修饰符:修饰符是对类本身特点的描述,包括 abstract、sealed 和 static。abstract 是抽象的意思,使用它修饰符的类不能被实例化;sealed 修饰的类是密封类,不能 被继承;static 修饰的类是静态类,不能被实例化。 - 类名:类名用于描述类的功能,因此在定义类名时最好是具有实际意义,这样方便用户理解类中描述的内容。在同一个命名空间下类名必须是唯一的。 - 类的成员:在类中能定义的元素,主要包括字段、属性、方法。 ## 访问修饰符 在 C# 语言中类定义后就要确定类中包含的内容,类中包含的内容被称为类中的成员。 类中的成员包括字段、属性、方法。每个类成员在定义时需要指定访问修饰符、修饰符。 类的访问修饰符主要有两个,即 internal 和 public,如果省略了访问修饰符,即为 internal。 1. public 成员可以被任何代码访问。 2. private 成员仅能被同一个类中的代码访问,如果在类成员前未使用任何访问修饰 符,则默认为 private。 3. internal 成员仅能被同一个项目中的代码访问。 4. protected 成员只能由类或派生类中的代码访问。 在修饰字段时通常用两个修饰符,即 readonly (只读)和 static (静态的)。 使用 readonly 修饰字段意味着只能读取该字段的值而不能给字段赋值。 使用 static 修饰的字段是静态字段,可以直接通过类名访问该字段。 需要注意的是常量不能使用 static 修饰符修饰。 ```C# 访问修饰符 修饰符 数据类型 字段名; ``` ## 方法的定义 方法是将完成同一功能的内容放到一起,方便书写和调用的一种方式,也体现了面向对象语言中封装的特性。 ```C# 访问修饰符 修饰符 返回值类型 方法名(参数列表) { 语句块; } ``` 其中: 1. 访问修饰符 所有类成员访问修饰符都可以使用,如果省略访问修饰符,默认是 private。 2. 修饰符 在定义方法时修饰符包括 virtual(虚拟的)、abstract(抽象的)、override(重写的)、static(静态的)、sealed(密封的)。override 是在类之间继承时使用的。 3. 返回值类型 用于在调用方法后得到返回结果,返回值可以是任意的数据类型,如果指定了返回值类型,必须使用 return 关键字返回一个与之类型匹配的值。如果没有指定返回值类型,必须使用 void 关键字表示没有返回值。 4. 方法名 对方法所实现功能的描述。方法名的命名是以 Pascal 命名法为规范的。 5. 参数列表 在方法中允许有 0 到多个参数,如果没有指定参数也要保留参数列表的小括号。参数的定义形式是“数据类型参数名”,如果使用多个参数,多个参数之间需要用逗号隔开。 ## get 和 set 访问器 属性经常与字段连用,并提供了 get 访问器和 set 访问器,分别用于获取或设置字段的值。 get 访问器和 set 访问器的使用与方法非常类似,可以在操作字段时根据一些规则和条件来设置或获取字段的值。 此外,为了保证字段的安全性,还能选择省去 get 访问器或 set 访问器。 ```C# public 数据类型 属性名 { get { 获取属性的语句块; return 值; } set { 设置属性得到语句块; } } ``` 其中: - get{} get 访问器,用于获取属性的值,需要在 get 语句最后使用 return 关键字返回一个与属性数据类型相兼容的值。 若在属性定义中省略了该访问器,则不能在其他类中获取私有类型的字段值,因此也称为只写属性。 - set{} set 访问器用于设置字段的值,这里需要使用一个特殊的值 value,它就是给字段赋的值。 在 set 访问器省略后无法在其他类中给字段赋值,因此也称为只读属性。 ## 调用类成员 调用类的成员实际上使用的是类的对象,对于创建类的对象,首先可以将类理解成一个模板,类的对象则是按照这个模板定制的一个对象。 创建类对象的语法 形式如下。 ```C# 类名对象名 = new 类名(); ``` 上面的语法形式是一种简单形式,通过“对象名”即可调用类中的成员。调用的语法形式如下。 ```C# 对象名 . 类的成员 ``` 给属性赋值的代码如下。 ```C# 类的对象 . 属性名 = 值; ``` 使用类的对象调用方法的代码如下。 ```C# 类的对象 . 方法名(参数); ``` 如果将类中的成员使用修饰符 static 声明,则在访问类成员时直接使用“类名.类成员”的方式即可。 ## 构造函数(构造方法) 创建类的对象是使用“类名 对象名 = new 类名()”的方式来实现的。 实际上,“类名()”的形式调用的是类的构造方法,也就是说构造方法的名字是与类的名称相同的。 构造方法的定义语法形式如下。 ```C# 访问修饰符 类名 (参数列表) { 语句块; } ``` 这里构造方法的访问修饰符通常是 public 类型的,这样在其他类中都可以创建该类的对象。 如果将访问修饰符设置成 private 类型的,则无法创建该类的对象。构造方法中的参数与其他方法一样,都是 0 到多个参数。 此外,构造方法是在创建类的对象时被调用的。通常会将一些对类中成员初始化的操作放到构造方法中去完成。 ## 析构函数 构造方法是在创建类的对象时执行的,而析构方法则是在垃圾回收、释放资源时使用的。 析构方法的定义语法形式如下。 ```C# ~类名() { 语句块; } ``` 在析构方法中不带任何参数,它实际上是保证在程序中会调用垃圾回收方法 Finalize()。 ## 方法重载(函数重载) 定义构造方法时提到可以定义带 0 到多个参数的构造方法,但构造方法的名称必须是类名。实际上,这就是一个典型的方法重载,即方法名称相同、参数列表不同。 参数列表不同主要体现在参数个数或参数的数据类型不同。在调用重载的方法时系统是根据所传 递参数的不同判断调用的是哪个方法。 ## 方法的参数(实参和形参) 方法中的参数分为实际参数和形式参数,实际参数被称为实参,是在调用方法时传递的参数;形式参数被称为形参,是在方法定义中所写的参数。 方法中的参数除了定义数据类型外,还可以定义引用参数和输出参数。引用参数使用 ref 关键字定义,输出参数使用 out 关键字定义。 引用参数在方法中使用时必须为其值,并且必须是由变量赋予的值,不能是常量或表达式。 如果需要将方法中的每一个参数都设置为 ref 类型参数,则需要在每一个参数前面加上 ref 关键字修饰。 引用参数与我们平时使用的参数有些类似,但输出参数不同,输出参数相当于返回值,即在方法调用完成后可以将返回的结果存放到输出参数中。 输出参数多用于一个方法需要返回多个值的情况。需要注意的是,在使用输出参数时,必须在方法调用完成前为输出参数赋值。 在调用含有带输出参数的方法时,必须在传递参数时使用 out 关键字,但不必给输出参数赋值。 ## struct:结构体类型 结构体与类比较相似,由于它是值类型,在使用时会比使用类存取的速度更快,但灵活性方面没有类好。 结构体从字面上来理解是指定义一种结构,实际上结构体是一种与类的定义非常相似的数据类型,但它是值类型。 结构体的定义位置与枚举类型一样,都是在类中定义或者在命名空间下定义,而不能将其定义到方法中。 在结构体中能定义字段、属性、方法等成员。定义的语法形式如下。 ```C# 访问修饰符 struct 结构体名称 { //结构体成员 } ``` 其中: 1. 访问修饰符 通常使用 public 或者省略不写,如果省略不写,代表使用 private 来修饰。 如果结构体中的内容要被其他类中的成员访问,需要将其访问修饰符设置为 public。 2. 结构体名称 命名规则通常和变量的命名规则相同,即从第二个单词开始每个单词的首字母大写。 3. 结构体成员 包括字段、属性、方法以及后面要介绍的事件等。 在结构体中也能编写构造器,但必须带参数,并且必须为结构体中的字段赋初值。 在调用结构体的成员时,能使用不带参数的构造器,与创建类的对象时类似。 结构体与类有些类似,但其定义却有很大区别,具体如下表所示 | 结构体 | 类 | | ----------------------------------------------- | --------------------------------------------- | | 允许不使用 new 对其实例化 | 必须使用 new 实例化 | | 没有默认构造方法 | 有默认构造方法 | | 不能继承类 | 能继承类 | | 没有析构方法 | 有析构方法 | | 不允许使用 abstract、protected 以及 sealed 修饰 | 允许使用 abstract、protected 以及 sealed 修饰 |