(五)多态

1.虚方法与方法重写

1.1 方法重写

  • 修改基类的某些方法的执行逻辑
  • 使用override这个关键词
  • 实现多态
    image

代码见CsharpStudy06

  • 重写方法必须把基类中的方法设置为虚方法,紧接着public关键词添加virtual修饰符。
  • 尽管我们使用的是shape基类中的绘制方法,可是,在代码运行过程中,编译器却能够准确识别出当前派生类的类型,并且执行派生类中的方法,而不是基类中的方法。
  • 这种调用同一个对象类型却产生不同表现形式的过程,我们就称它为多态。

2.多态

2.1 多态的好处

  1. 可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
  2. 可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的任何特性的运行和操作。而新加入的子类也同样具有多态的功能。
  3. 接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
  4. 灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
  5. 简化性(simplicity)。多态可以简化代码编写和修改的过程,尤其可以集中处理大量对象的运算和操作,这个特点在多态中尤为突出和重要。

值得注意的是,多态并不能够解决提高执行速度的问题,因为它基于动态装载和地址引用,或称动态绑定。但在Java中,除了final类和一定条件下的final方法外,所有方法都由JVM在运行期间进行动态绑定。

通过多态,我们可以把数据模型的业务逻辑集中处理,不仅顺利为业务做出了封装、解耦了系统各部分的代码,而且还能让整体执行过程更简单的、代码更加容易维护。

3.抽象类与抽象成员

image
image

如果我们使用了abstract关键词,那么在做方法重写的时候virtual就可以不使用了。

3.1 规则

接下来,我们了解一下抽象类和抽象成员在c#中的使用规则。

  • 一个成员属性或者成员方法被声明为abstract以后,这个属性或者方法是不可以有代码实现的
  • 当一个成员属性或者成员方法被声明为abstract以后,整个class都需要被声明为抽象类
  • 派生类必须实现抽象类中所声明的所有抽象方法和抽象属性。
  • 抽象类不可以被实例化。当我们声明了一个抽象的shape类以后,我们不能使用new关键词来创建shape对象。

3.2 why

其实抽象只是一种概念、一种设计方式的集中体现,用了抽象将会对我们接下来的代码拓展产生设计理念的限制,强制团队中其他程序员跟随当前的设计思想继续展开实现。

如果draw方法不是抽象方法而是一个虚方法,那么在circle类中,我们可以不对draw方法进行重写。那么在程序执行过程中必然会出现业务逻辑上的错误。

抽象类中也可以定义普通方法,,也不需要被派生类重新定义。

4. sealed类与sealed成员

  • 使用 sealed 修饰符,
  • 可以防止当前类被继承或者防止派生类在继承的过程中重写某个方法。
  • 与abstract抽象修饰符类似,sealed 修饰符不仅可用来 修饰class,同样也可以修饰类成员。
  • 如果sealed关键词用在class上,那么这个类将无法被别人继承;
  • 而如果 sealed关键词用在成员方法上,那么这个方法将无法被重写。

4.1 为什么要使用sealed

在微软官方的MSDN文档说的很清楚了,使用 sealed 来修饰的类在运行效率上会有一点点的提升,因为编译器在程序运行的时候,会针对密封类作一定的优化。
image

https://docs.microsoft.com/zh-cn/dotnet/standard/design-guidelines/sealing
image
在真正工作中,这种性能的提升几乎没有太大的意义。

而在MSDN文档中也明确说明,“ 若无必要,请勿使用”。文档告诉我们,如果一个类满足以下几个情况,我们是可以使用密封修饰符的。

  1. 静态类
  2. 需要存储敏感的数据
  3. 虚方法太多,重写的代价过高的时候
  4. 追求性能提升

c#中的字符串类,string class,就是密封的,我们无法继承它。那么如果我们需要对string类做一些额外的操作,该怎么处理呢?这个时候,c#为我们提供了类的拓展操作,使用extension方法。

posted @ 2023-09-14 09:01  huihui不会写代码  阅读(49)  评论(0)    收藏  举报