前言
我以前没有很深入的去理解过多态,在敲了一些代码之后,回过头看这些解释性的语句,顿悟了这些是什么意思
面向对象六大原则
- 单一职责原则
- 开闭原则
- 里氏转换原则
- 依赖倒置原则
- 接口隔离原则
- 迪米特原则
- 面向对象有三大特性 封装 继承 多态
- 在继承关系下,实例化出不同的对象,这些对象调用相同的方法,但是却表现出不同的行为,这就叫多态
多态
- C# 中体现多态的三种方式, 虚方法,抽象类,接口
虚方法
- 父类中用virtual修饰的方法,可以用于实现该方法共有的功能,然后在子类重写该方法时,使用base关键字调用父类中的该方法
里氏转换原则
- 子类对象可以直接赋值给父类变量
- 子类对象可以调用父类中的成员,但是父类对象永远只能调用自己的成员
- 如果父类对象中装的是子类对象,可以将这个对象强制转换为子类对象
is 与as两者都是进行类型转换
- is转换成功,返回true, 否则返回false
- as转换成功,返回对应的对象,失败返回null
必须使用里氏原则才能解决的问题
抽象方法(方法足够虚没有任何方法体的时候)
- 虚方法是有方法体的,抽象方法没有方法体
- 抽象方法必须被子类实现
- 用关键字abstract 关键字修饰
注意事项
- 抽象方法必须在抽象类中,抽象类不一定要有抽象方法
- 抽象类不能被实例化
使用场景
- 父类中的方法不知道如何实现,可以将父类写成抽象类,将方法写成抽象方法
- 父类中的方法有默认实现,且父类需要被实例化,可以将父类定义成一个普通类,用虚方法实现多态
- 如果父类中的方法没有默认实现,父类也不需要被实例化,可以将该类定义为抽象类
接口(抽象类中的方法都是抽象方法的时候)
- 可以把这个抽象类用接口的形式来表现
- 用关键字interface
- 不能包含字段,但是可以包含属性
- 使用自动属性
- 不能有方法体,全是抽象方法,但是不需要用abstract修饰
- 不能有访问修饰符,默认全是public
注意事项
- 接口中所有方法都是抽象方法,所以接口不能被实例化
- 一个类可以实现多个接口,被实现的多个接口用逗号隔开
- 一个接口可以继承多个接口,接口之间也要用逗号隔开
- 类与类之间是单继承
使用场景
- 接口是一种能力,一种规范,当我们对现在已经存在的类的继承关系进行扩展的时候,可以用接口来完成相应的工作
属性
- 属性分为两种,常规属性和自动属性
- 自动属性 不需要写对应的字段,C#编译器会自动给我们的属性添加一个对应字段
public int Age{get; set;} //如果只是单纯的取值和赋值,可以用自动属性
使用场景对比
- 虚方法 父类中的个别方法用虚方法实现,子类继承可以重写
- 抽象类,父类定义一系列的规范,子类去把父类中的规范全部实现
- 接口 一种功能扩展,在原有的类的继承关系以外新功能的扩展
封装之访问修饰符
- 五种修饰符
- private 只能在当前类内部进行访问使用,子类,实例对象都访问不到 【私有访问】
- public 当前类,子类,实例对象,都可以访问到 【公开访问】
- internal 只能在当前程序集(项目)中访问 【内部访问】
- protected 只能在当前类的内部,以及该类的子类中访问,实例对象访问不到 【受保护访问】
- protected internal 就是两种访问权限相加
修饰类
- 能够修饰类的访问修饰符只有两个,public和internal
- 类的默认访问修饰符是internal
修饰类成员
- 五种访问修饰符都可以修饰类中的成员
- 类中的成员默认访问修饰符是private
静态
静态字段
- 被static关键字修饰的字段,叫做静态字段
- 静态字段可以重新赋值
- 静态字段存储的数据在内存中只有一份
- 静态成员只能通过 类名.成员名 访问,实例对象无法访问
静态属性
- 静态属性用于封装静态字段,不能用于封装非静态字段
- 因为静态类成员是先于非静态的类成员存在的
静态方法
- 用static修饰的方法 用类名.静态方法名 调用
- 在静态方法中不能调用非静态成员
- 在普通方法中可以调用静态成员
静态构造方法
- 一个类只能有一个静态构造方法
- 用于初始化静态成员 ,没有任何访问修饰符,也没有参数
- 可以定义在静态类中,也可以定义在非静态类中
- 静态构造方法会在程序创建第一个实例或者引用任何静态成员之前,完成类中静态成员的初始化
静态类
- 当类中成员全部是静态成员时候,可以声明为静态类
- 加上关键字 static
- 静态类中不能存在非静态成员
- 静态类不能实例化对象
注意
- 先有静态成员,后有实例成员,后可以调用先出现的
装箱与拆箱
- 装箱 值类型——引用类型
- 拆箱 引用类型——值类型
- 两种类型只有存在继承关系的时候,才可能出现装箱或拆箱操作
- 装箱和拆箱本质上是数据存储在栈空间和堆空间的变更,频繁的装拆会降低运行速度,尽量少用
预编译指令(在程序正式编译之前执行 不会转化成可执行代码中的命令)
- 区域指令
#region Info
......
#endregion
对象初始化器
- 语法格式
类名 对象名 = new 类名(){属性名 = 值, 属性名 = 值};
- 应用场景 当一个类中的属性很多很多时,不可能为各种情况都定义构造方法,可以用对象初始化器来完成属性的赋值
- 类中不必有构造方法