文档章节

深入浅出OOP(三): 多态和继承(动态绑定/运行时多态)

葡萄城控件技术团队
 葡萄城控件技术团队
发布于 2015/04/28 09:36
字数 1337
阅读 866
收藏 36
点赞 0
评论 2
OOP

在前面的文章中,我们介绍了编译期多态、params关键字、实例化、base关键字等。本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定。

 

运行时多态或迟绑定、动态绑定

在C#语音中,运行时多态也叫方法重写(overriding),我们可以在子类中overriding基类的同签名函数,使用“virtual & override”关键字即可。

 

C#的New、Override关键字

image

创建一个console 示例工程,命名为InheritanceAndPolymorphism。在Program.cs基础上,再添加2个类文件,分别命名为ClassA.cs、ClassB.cs。拷贝如下代码:

public class ClassA
    {        public void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }        public void BBB()
        {
            Console.WriteLine("ClassA BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassA CCC");
        }
    }

 

ClassB:

public class ClassB
    {        public void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }        public void BBB()
        {
            Console.WriteLine("ClassB BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassB CCC");
        }
    }

在上面的代码中,我们可以看到ClassA、ClassB有同样签名的方法,可以在program.cs中直接使用。

我们对代码再做休整,结构如下:

/// <summary>
    /// ClassB, acting as a base class    /// </summary>
    public class ClassB
    {        public void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }        public void BBB()
        {
            Console.WriteLine("ClassB BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassB CCC");
        }
    }    /// <summary>
    /// Class A, acting as a derived class    /// </summary>
    public class ClassA : ClassB
    {        public void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }        public void BBB()
        {
            Console.WriteLine("ClassA BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassA CCC");
        }
    }

 

Program.cs

 
     
        Main(= ==

F5,运行代码,结果如下:

ClassA AAA

ClassA BBB

ClassA CCC

ClassB AAA

ClassB BBB

ClassB CCC

ClassB AAA

ClassB BBB

ClassB CCC

但同时,在VS的Output窗口,我们获得了3个Warnings:

'InheritanceAndPolymorphism.ClassA.AAA()' hides inherited member

'InheritanceAndPolymorphism.ClassB.AAA()'. Use the new keyword if hiding was intended.

'InheritanceAndPolymorphism.ClassA.BBB()' hides inherited member

'InheritanceAndPolymorphism.ClassB.BBB()'. Use the new keyword if hiding was intended.

'InheritanceAndPolymorphism.ClassA.CCC()' hides inherited member

'InheritanceAndPolymorphism.ClassB.CCC()'. Use the new keyword if hiding was intended.

这些Warnings的原因是因为子类和基类的AAA、BBB、CCC方法签名相同,尽管从执行上看优先执行子类同签名的方法,但是可能会有潜在的问题,故Warnings提出。

 

重构实验

基于上面的Warning,我们手动修改代码,看看如何消除这些Warnings。

先给子类添加new、override关键字试试:

/// <summary>
    /// Class A, acting as a derived class    /// </summary>
    public class ClassA : ClassB
    {        public override void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }        public new void BBB()
        {
            Console.WriteLine("ClassA BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassA CCC");
        }
    }

 

执行的结果是报错了:

Error: 'InheritanceAndPolymorphism.ClassA.AAA()': cannot override inherited member 'InheritanceAndPolymorphism.ClassB.AAA()' because it is not marked virtual, abstract, or override

 

image

从这个错误提示信息看,我们需要修改基类方法,如添加virtual关键字。

 
     
            
     
           
     
        Main(= = =

执行,则无Warning了,通过这个实例,我们得知通过在基类添加Virtual关键字授权其子类可override基类同签名方法的权限,方便了OOP的扩展。

 

3个类的运行时多态

ClassA\ClassB基础上,下面添加ClassC,看看3个类继承关系的运行时多态:

 
     
            
     
            
     
         
     
        Main(= = =

运行结果:

ClassB AAA

ClassB BBB

ClassA CCC

ClassB AAA

ClassB BBB

ClassA CCC

ClassC AAA

ClassA BBB

ClassA CCC

如果基类声明了virtual 关键字,子类可使用override修饰符实现运行时多态:只有在编译器动态决定是否被调用。

如果未标明virtual或非virtual,则方法是否被调用在编译期就能决定。

 

image

 

再看看下面的例子:

internal class A
    {        public virtual void X()
        {
        }
    }    internal class B : A
    {        public new void X()
        {
        }
    }    internal class C : B
    {        public override void X()
        {
        }
    }

F5运行,结果报错了:

Error: 'InheritanceAndPolymorphism.C.X()': cannot override inherited member 'InheritanceAndPolymorphism.B.X()' because it is not marked virtual, abstract, or override

错误的原因是A中定义了virtual的X函数,在B中用new关键字隐藏了A中的X函数。当C尝试通过override关键字的时候,是获得不了A中的virtual关键字X函数的,既在C中X函数为非Virtual的,故不能override。

 

切断关系

           
     
        Main(= =

执行结果如下:

Class: A ; Method X
Class: C ; Method X

image

在这里,我们通过在B类中添加new Virtual修饰符,然后在C中即可使用B中Virtual的X函数了。

 

4个类的运行时多态

image

在上面继承上,在运行时多态中添加第四个类:ClassD。

 
     
        
     
        
     
         
     
        
     
        Main(= = ==

 

执行结果如下:

ClassB XXX

ClassB XXX

ClassD XXX

ClassD XXX

第一行输出中,来自a.XXX()函数 , 我们在 ClassA中定义了XXX函数,然后在ClassB中使用new关键字切断了virtual关系--对子类而言。因此XXX函数从ClassC开始成为新的virtual函数,在这个代码中a是ClassD的实例,但是声明的为ClassA,故从下往上找,找到ClassB的XXX函数,打印并输出结果。

 

永无止境的循环

 

 
     
        
     
        
     
        Main(=

运行报错:

Error: {Cannot evaluate expression because the current thread is in a stack overflow state.}

在这个例子中,((ClassA)this).XXX(); 导致了循环调用,修改为base.XXX即可修复这个强转导致的循环调用。

 

结论

  • 在C#中,子类对象可赋值给一个基类对象;相反需要强转。

  • override关键字用于子类重写同签名的基类virtual函数

  • 用new和override可重写基类virtual的同签名函数

  • virtual修饰符的函数,只能在运行时决定是否被执行

  • 函数未用virtual修饰,则在编译期即可决定是否被调用

 

原文链接:Diving in OOP (Day 3): Polymorphism and Inheritance (Dynamic Binding/Run Time Polymorphism)

© 著作权归作者所有

共有 人打赏支持
葡萄城控件技术团队

葡萄城控件技术团队

粉丝 321
博文 487
码字总数 694630
作品 13
西安
高级程序员
加载中

评论(2)

葡萄城控件技术团队
葡萄城控件技术团队

引用来自“lee1994522”的评论

感谢!请问这个深入浅出OOP系列还会有后续吗?
还有的。
lee1994522
lee1994522
感谢!请问这个深入浅出OOP系列还会有后续吗?
深入浅出OOP(六): 理解C#的Enums

MSDN定义:枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。 例如,假设您必须定义一个变量,该变量的值表示一周中的一天。 该变量只能存储七个有意义的值...

葡萄城控件技术团队 ⋅ 2015/06/02 ⋅ 0

深入浅出OOP(五): C#访问修饰符(Public/Private/Protected/Inter

深入浅出OOP(五): C#访问修饰符(Public/Private/Protected/Internal/Sealed/Constants) 访问修饰符(或者叫访问控制符)是面向对象语言的特性之一,用于对类、类成员函数、类成员变量进行访问...

葡萄城控件技术团队 ⋅ 2015/05/26 ⋅ 0

java基础-多态是什么?

1.1 什么是多态? 多态是继数据抽象和继承之后的第三种基本特征。 定义:多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。引用C...

KongFanhao ⋅ 2016/09/18 ⋅ 0

深入浅出OOP(一): 多态和继承(早期绑定/编译时多态)

在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现。 无论作为软件设计的高手、或者菜鸟,对于架构设计而言,均需要多次重构、取舍,以有利于整个软件项目的健康...

葡萄城控件技术团队 ⋅ 2015/04/02 ⋅ 0

《Thinking in Java》Eight 多态

在OOP编程语言中,多态是继数据抽象和继承之后的第三种基本特征。 动态绑定(后期绑定/运行时绑定):在运行时根据对象的类型进行绑定。也就是编译器一直不知道对象的类型,但方法调用机制能...

DouDouLee ⋅ 2016/04/05 ⋅ 0

C++学习笔记(12)——多态与虚函数

本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一、小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正! 多态与虚函数 1.多态性 多态的概念: l 在面向对象的概念中,...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

面向对象编程(OOP)概述

 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。 一、面向对象编程的基本概念: 面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承...

YuanyuanL ⋅ 2015/08/07 ⋅ 0

OC学习笔记十二 多态

一.多态概念 多态的前提,必须存在继承关系,在代码中的表现形式就是父类类型保存子类类型,即父类的指针指向子类对象。 二.多态特性 在OC中,调用方法是,会检测对象的真实类型,称为动态绑...

卧龙小 ⋅ 2014/10/16 ⋅ 0

Java总论及三大特性理解

1、对象(object) 万物皆为对象(根类Object类)。 程序是对象的集合(面向对象程序设计语言OOP)。 每个对象都有自己的由其他对象所构成的存储(对象有成员属性)。 每个对象都拥有其类型(...

斯武丶风晴 ⋅ 2015/07/23 ⋅ 0

think in java第八章多态 总结随笔

多态:基于继承的向上转型功能,允许同一种类型同一行为有不同的表现。 多态的优点:多态不但能够改善代码的组织结构和可读性,还能够创建可扩展的程序—即无论在项目最初创建时还是在需要添...

The_flying_pig ⋅ 2017/06/20 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

原创小博客 ⋅ 今天 ⋅ 0

聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it ⋅ 今天 ⋅ 0

二分查找

二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

人觉非常君 ⋅ 今天 ⋅ 0

VS中使用X64汇编

需要注意的是,在X86项目中,可以使用__asm{}来嵌入汇编代码,但是在X64项目中,再也不能使用__asm{}来编写嵌入式汇编程序了,必须使用专门的.asm汇编文件来编写相应的汇编代码,然后在其它地...

simpower ⋅ 今天 ⋅ 0

ThreadPoolExecutor

ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

4rnold ⋅ 昨天 ⋅ 0

Java正无穷大、负无穷大以及NaN

问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

young_chen ⋅ 昨天 ⋅ 0

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 昨天 ⋅ 0

实验楼—MySQL基础课程-挑战3实验报告

按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

zhangjin7 ⋅ 昨天 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 昨天 ⋅ 0

Java桌球小游戏

其实算不上一个游戏,就是两张图片,不停的重画,改变ball图片的位置。一个左右直线碰撞的,一个有角度碰撞的。 左右直线碰撞 package com.bjsxt.test;import javax.swing.*;import j...

森林之下 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部