面向对象编程基础2(干货)
概念1:继承
1.C#语言的继承方式为单继承。继承中的基类代表父类,继承者称为派生类。
2.隐藏方法:如果想在派生类中定义一个和基类中重名的方法,但是实现过程不一样,这中操作叫隐藏方法。
注意:为屏蔽父类中的那个方法,派生类中声明名称和类型、及函数名都要与父类的对应的方法相同,且声明这个方法的时候要用new关键字。
3.虚方法和多态:面向对象编程中,都遵循一个原则,依赖导致原则。换句话说就是,程序要依赖于抽象类(pet),而不是依赖于具体类(Dog)如上图。
目的:统一提高效率,但是又存在子类差异性如何体现问题。
概念:虚方法--声明为virtual的方法即为虚方法,基类的虚方法可以在派生类中使用override进行重写。
多态--通过指向派生类的基类(统一)调用,调用虚函数,会根据引用所指向派生类的实际类型,调用派生类中的同名重写函数,即为多态(个性张扬)。比如下图,基类中的虚方法为Speak(),派生类中可以使用override关键字对Speak()方法进行重写。
4.构造函数小补充
小概念:容器构造函数,若多个派生类都继承与一个基类,那么在new他的时候,一个个的new很麻烦,所以有了容器构造函数来减少代码量,也更加清晰。
虚方法和多态的额外特点:
1.虚方法必须和基类中的方法有相同的可访问性,且基类方法不能使private
2.不能重写static方法或者非虚方法(即没有使用virtual声明的方法)
3.方法、属性、索引器、时间,都可以声明为virtual或者override。
调用顺序:
5.抽象方法和抽象类:解释一下,就是比虚方法更需虚的方法,为什么呢,虚方法里面可以有实现的代码块,但是抽象方法里面是不允许有的。关键字abstract。
特点:必须是方法、属性、事件、索引
必须使用abstract修饰符标记
不能有实现的代码块!!!!!!!!!!!
概括一下:
抽象类的存在只有一个目的,就是被集成。
抽象类不能被实例化,使用abstract修饰。
抽象类可以包含抽象成员和普通成员,以及他们之间的任意组合。
抽象类的抽象成员在派生类中需要使用override关键字实现。
6.密闭类和密闭方法:关键字是sealed。
密闭类就是不希望其他人通过继承来修改,密闭方法就是不希望他人重写该方法。
一般基类方法不希望被子类重写,就可以不声明为virtual。如果是派生类方法不希望子类对其重写,同时是override重写,就可以使用sealed机制。这种方法一般针对于子类没必要进行重写的事件,比如,狗子就是汪汪叫,不可能喵喵叫啊。所以,狗子的派生类,无论是金毛啊,哈士奇啊,土狗啊,都是汪汪叫。
7.接口:接口是指定一组函数成员,而不实现他们的引用类型。关键字interface。
特点:比抽象更抽象的,有点像完全没有普通函数和数据的抽象类。
里面的方法默认是public,但是却不可以添加任何修饰符,也就是说,他一定是public!!
接口仅仅可以用来被实现!!他是一种引用类型,可以通过对象和接口进行调用,虽然C#是单继承,但是却是多接口。
8.结构和类:结构是值类型,存储在栈中;类是引用类型,存在堆中。
结构不支持继承,类支持继承。
结构不能定义默认的构造函数,编译器会定义。
使用场合:结构:由于分配内存快,作用域结束即被删除,不需要垃圾回收,用于小型的数据结构,但传递过程中会赋值,应该使用ref关键字提高效率。
类:用于其他的需要继承体系的场合。
概念2:静态成员
1.关键字static -- 标记为static的字段、方法、属性、构造函数、事件就是静态成员。例:static int num;
2.静态成员将被类的所有实例共享,所有的实例都访问同一内存位置。(即为公共财产)
3.访问方式
4.静态函数成员:静态函数也独立与任何实例,没有实例也可以调用,静态函数不能访问实例成员,仅能访问其他静态成员。
5.静态构造函数:用于初始化静态字段。
在引用任何静态成员之前,和创建任何实例之前调用。
与类名相同,使用static,无参数,无访问修饰符。如图中的static Dog()
6.静态类:如果只包含了静态方法和属性,并且标识为static,则定义为静态类。
静态类不能创建实例,不能被继承。
可以为静态类定义一个静态构造函数。
静态类主要用于基础类库(如数学类 Math类)和扩展方法。可以用数学上的定力来理解。自带的那些。
扩展方法:如果有源代码,直接添加一个新方法。
如果不能修改但是也不是密闭类,可以派生子类扩展。
如果以上条件都不满足,可以使用静态类扩展方法。
要求:扩展方法所属的类,必须是static类。
扩展方法本身必须是一个static方法
扩展方法的第一个参数类型,必须是this+类名。
概念3:重载和操作符
1.装箱:值类型变成引用类型 -- 隐式转换。implicit关键词
2.拆箱:引用类型变成值类型 -- 显示装换。explicit关键词
3.重载运算符:利用现有的某种运算符,针对自定义类或者结构,实现某种运算的操作。
比如:公狗+母狗=小狗 -- 把加号重新定义,定义为制造小狗的过程。
语法细节:关键字operator+运算符
概念4:泛型
1.泛型类:可理解为一个模子,装入类型的材料,就可以塑造出想要的产品。
2.语法展示:
3.泛型使用的原因:
4.泛型实例化过程
5.泛型类优势:代码量更小。
只有需要的类型才会被实例化
易于维护,修改模板,所有的实例都会改变。
6.泛型方法:泛型方法就是方法的模型,给定具体的类型,就可以实例化出一个操作该类型的具体方法。(泛型方法可存在于泛型类和普通类中)
7.语法展示:
8.约束:约束就是控制泛型的控制器。目的是缩小泛型参数的范围。泛型类和方法都可以添加约束,只有添加了约束,才能调用泛型参数中的方法,否则只能调用那些其他的方法。关键词where。
9.泛型接口:泛型接口允许我们将接口成员的参数和返回类型设置为泛型参数的接口。
定义及实现:
概念5:集合
1.预定义常用的集合。
动态数组:ArrayList 列表:List 字典:Dictionary 队列:Queue 栈:Stack
2.动态数组:初始化,可以不指定大小。
获取长度使用Count属性
添加使用Add,删除使用Remove,RemoveAt
访问[index]
3.更好用的List<T>:ArrayList是类型不安全的,而且有装箱拆箱的性能问题,于是出现List<T>
4.字典Dictionary<TKey,Tvalue>:字段容器存储是一系列的键值对,每个值对应一个唯一的键。键的意义在于,我们可以通过键相对高效的访问到值。意思就是字典里面的目录和内容的关系一样。
字典操作:数量 Count;添加 Add(key,value);删除 Remove;访问:[key],也就是查目录即可。
5.栈:出栈 Pop;入栈 Push;获取栈顶元素:Peek
6.队列:出队 Dequeue;入队:Enqueue
概念6:事件和委托
1.委托:委托就是持有一个或者多个方法的对象!并且该对象可以执行,可以传递。关键字delegate。
2.Lambda表达式 表示方法 =>
3.事件 事件分为发布者和订阅者两个部分。对应的方法分别为事件的触发和注册。
用程序解释就是,事件发生时,通知订阅者,就是调用订阅者的注册函数。注册,就是告诉发布者调用哪一个注册函数。
事件关键词event,事件的声明和触发。
面向对象编程总结:
1.继承
继承 -- 通过基类对类进行统一管理
接口 -- 将汉武关联的对象进行统一管理
虚方法、多态 -- 对函数进行重写,突出子类的个性
密闭方法 -- 终止继承的一种方式
2.静态类和静态成员。
静态是一种共享机制,在某一类中,如果想要公用某些数据,则可用静态来实现。
3.操作符重载
装箱拆箱:
优势:统一管理
劣势:性能损耗、安全风险。
运算符重载:对运算符赋予新的概念
4. 泛型
泛型类、泛型接口、泛型方法。(目的:使得对象获得最大化的扩展)
5.集合
动态数组,列表;字典;栈;队列 (目的:管理对象)
6.委托
委托;Lambda表达式;事件 -- (用于对象之间的通讯方式)