1、面向对象思想 (1)什么是面向对象 -> 思考方式(面向过程是解决问题的步骤、面向对象是解决方案) -> 代理模式(找专业的人做专业的事,不是所有事都一个人实现) (2)面向对象的三大特征 -> 封装性、继承性、多态性 (3)类与对象的理解(跟具体情况相关) -> 类是模型、对象是产品 -> 类:是一个类型。 -> 对象:类的实例。 2、.NET Framework类库 (1)概述 ->.NET Framework 包括可加快和优化开发过程并提供对系统功能的访问的类、接口和值类型。 ->.类:NET Framework 提供了一组丰富的接口以及抽象类和具体(非抽象)类。可以按原样使用这些具体的类,或者在多数情况下从这些类派生您自己的类。 ->接口:若要使用接口的功能,既可以创建实现接口的类,也可以从某个实现接口的 .NET Framework 类中派生类。 ->.NET Framework类对象: (A)Object:对象层次结构的根。C#数据类型为object。 (B)String: Unicode 字符的不变的定长串。C#数据类型为string。 (2)命名约定 ->.NET Framework 类型使用点语法命名方案,该方案隐含了层次结构的意思。 ->此技术将相关类型分为不同的命名空间组,以便可以更容易地搜索和引用它们。 ->全名的第一部分(最右边的点之前的内容)是命名空间名,最后一部分是类型名。 例如:System.Collections.ArrayList表示ArrayList 类型,该类型属于 System.Collections 命名空间。该命名空间中的类型可用于操作对象集合。 (3)命名空间 System 命名空间是 .NET Framework 中基本类型的根命名空间。 此命名空间包括表示由所有应用程序使用的基本数据类型的类:Object(继承层次结构的根)、String 、Array和Int32、Char、Byte等。 3、类与对象(部分细节请参考“2.3 面向对象 静态、引用类型、引用、异常等.txt”) (1)类的概念: 类是一个数据类型,是C# 中功能最为强大的数据类型,像结构一样,类也定义了数据类型的数据和行为。程序员可以创建作为此类的实例的对象。 与结构不同,类支持继承,而继承是面向对象编程的基础部分。 类和结构的比较: 结构与类共享大多数相同的语法,但结构比类受到的限制更多: 在结构声明中,除非字段被声明为 const 或 static,否则无法初始化。使用时所有字段要初赋值。 结构不能声明默认构造函数(没有参数的构造函数)或析构函数。(结构是值类型) 结构不能从类或其他结构继承。因为所有值类型都已继承自 ValueType,后者继承自 Object。 (2)类的定义: 从已有类派生自己的类,若没有指定父类,默认的直接继承自Object类 值类型(结构类型)定义public struct Char{}public struct Int32{}用struct关键字 引用类型(类类型)定义public sealed class String{}用class关键字 (A)用class关键字定义整个类 [访问修饰符] [abstract] class 类名 //用关键字class定义 { // 成员(包括字段、属性、方法、构造方法、索引器、事件、委托、结构等) } (B)用partial class关键字定义部分类,如: public partial class MyClass { string firstName; string lastName } public partial class MyClass { int age; int Num; } (3)创建类的实例 声明MyClass类型的变量(C#强类型,每个变量和对象必须具有声明的数据类型) MyClass mc; //此时还没有实际的包含对象数据,没有指向一个对象。 创建MyClass类的新实例(对象)(使用new关键字) 将创建的实例(对象)赋给变量,完成了实例化。 mc = new Myclass(); //此处可以通过构造方法或初始化器赋初值 以上两步可以合在一起完成:MyClass mc= new Myclass(); 完成对象实例化后,才是创建好了一个可用的实例,才可以访问实例中的成员。 (4)类与对象: 创建(new)一个对象的时候,系统在内存中为这个实例(对象)开辟了一块内存空间(堆),并给对象的字段赋默认初始值,为了方便访问,将能唯一标识这个对象地址的值赋给变量mc(栈),使得通过mc可以访问这个对象。 赋值之后,就用mc来指代这个对象了。所以直接说mc是MyClass类的一个对象。
以下代码中的p1和p2是相等的,可以看作是同一个对象的两个名称(正名别名) 换言之,p1和p2就是MyClass类的同一个对象! static void Main(string[] args) { Person p1 = new Person(); p1.Name = "佳木斯"; p1.Age = 21; Person p2 = p1; Console.Write(p1==p2); //打印 true } 类是对象的模板,对象是类的实例,每个对象在与内存中开辟一块空间,各字段都有具体值的。 4、类的成员分类 实例成员:默认情况非静态(static)、非常量(const)的所有成员都是实例成员。 静态成员:static修饰的字段,属于类,不属于类的每个实例,用类名+点实现读写访问。 常量成员:const 隐式静态常量,不能修改的,用类名+点实现只读访问。 函数成员:属性(特性)、构造函数、方法、索引器、事件、委托等。 访问修饰符:成员前不写修饰符等价于private,要在类外部被访问,必须加public。 类的内部是class下面的花括号,不写public只有与main方法在一个类里才可以执行。 5、字段(访问修饰符及封装) 字段一般默认设为私有,提供属性给外界访问,在属性中可以对访问做权限限制。 封装字段生成属性快捷键:Ctrl+r,e 然后2次回车 6、属性 (分为只读属性,只写属性,可读可写属性) (1)属性(特性) 字段需要保护起来,所以设为私有;外界需要访问的通过属性实现。 (A)属性里面包含两个部分,get,set 这两个部分分别表示:get表示返回字段的值,set表示设置字段的值。 (B)属性就是从外界访问字段的渠道。 字段用骆驼(camelCase)命名法,属性用帕斯卡(PascalCase)命名法 (C)属性可以控制外部赋值的逻辑和返回的值的逻辑。 在类的内部赋值,直接使用字段即可,如果对字段的赋值有约束筛选等判断,使用属性 (D)属性在本质上就是方法,其中get{}是一个方法,set{}是一个方法。 (E)属性不具备存储能力。 (2)自动属性 使用自动属性时,虽然没有定义字段,但是系统在后台生成了与属性对应的字段来实现存储的需要:接收赋值以及向外返回值。 针对自动属性的set和get部分,系统也生成了相应的代码来实现功能。 7、构造方法 (1)写一个类系统会自动生成(无参的)构造方法。 (2)构造方法是为了在new的时候初始化对象,给对象字段赋初值。 new Myclass()中的“MyClass()”就是在调用构造方法赋值。 (3)手动添加构造方法以后,按需要来赋初值。 系统自动生成的无参构造方法就不存在了,需手动添加无参构造方法,才不会出错。 (4)构造方法是可以重载的 附:初始化时,没有显式赋值的字段的值,数字类型 0,char ‘\0’,bool false,其他null。 8、构造方法中的this和base关键字 (1)this关键字表示对象的当前实例,base表示父类。用来指明成员所在的类。 (2)this用来调用本类构造方法,base用来调用父类构造方法。 this用法1:将当前对象作为参数传递给另一个方法 this用法2:如果实例成员中具有与形参相同的名称,使用this关键字可解决这种歧义。 public void SetName(string FirstName,string LastName) { this.FirstName= FirstName; this.LastName= LastName; } 9、封装 属性是对字段的封装 方法是对过程的封装 类是对对象的封装(特征与功能) 程序集是对类库的封装(*) (1)封装的应用实例:建一个dll文件夹,将dll文件放进来,添加引用即可调用 注意:生成.dll类库文件,需要在新建项目的时候选择“类库”。 (2)封装的应用实例:在一个项目调用另一个项目中的方法需要注意: (A)添加引用,导入命名空间 (B)被调用的方法所在的类需是用public修饰的。 (C)被调用的方法本身需是用public static修饰的,否则需创建类的实例调用。 (D)两个项目的类不要重名,否则就需要写全命名空间才能调用。 10、继承之里氏转换原则 第1条:子类对象可以直接赋值给类对象(子类可以隐式转换为父类) 第2条:指向子类的父类对象,可以强制转化为该子类对象 is运算符:if(对象 is 类型)与 第2条配合使用 示例:造人(Teacher、Student继承自Person类)
static void Main(string[] args) { Teacher t = new Teacher("胡安明",'男',23); Student s = new Student("皓皓",'女',27,"瑜伽"); Teacher tt = new Teacher("黄小明",'男',32); Person[] p = {t,s,tt}; //第1条 子类隐式转换为父类 for (int i = 0; i < p.Length; i++) { if(p[i] is Student) { Student s1 = (Student)p[i]; s1.SayHello(); } else { Teacher t1 = (Teacher)p[i]; t1.SayHello(); } } }
附:C#是类型安全的语言 -> 什么类型的数据,只能赋值给什么类型的变量 -> 什么类型,只能访问该类型的成员(通过点) 附:is运算符和as运算符 对象 is 类型;//返回bool值 子类类名 变量 = 父类变量 as 子类;//转换成功完成赋值,不成功赋null。 11、继承之构造方法的执行: new的时候调用构造方法,(其他时候不能用),执行时先去调用父类的构造方法,然后再执行子类的构造方法的方法体 ->默认地调用父类的(无参)构造方法,如果父类中添加了有参的构造方法,无参构造方法就没有了。会报错!处理:给父类添加无参构造方法; ->如果要调用父类的有参构造方法,让子类指定调用父类的构造方法 //父类构造方法
public Father() { } public Father(int n, string nm, char s) { num = n; name = nm; sex = s; } public class Son : Father { public static int count; public Son(): base(11, "jam",'男') //子类构造方法,用base()调用父类的方法 { } }