review——C# (6)虚方法和覆写方法
FROM P125
在上一节中看到,当使用基类引用访问派生类对象时,得到的是基类的成员。虚方法可以使基类的引用访问“升至”派生类内。
可以使用基类引用调用派生类(derived class)的方法,只需满足下列条件:
□派生类的方法和基类的方法有相同的签名和返回类型
□基类的方法使用virtual标注
□派生类的方法使用override标注
使用方法如下例:
1 class MyBaseClass //基类 2 { 3 virtual public void Print(); 4 } 5 class MyDerivedClass : MyBaseClass //派生类 6 { 7 override public void Print() 8 }
与上一节中不同,使用基类引用调用Print方法时,方法调用被传递到派生类并执行,因为:
□基类的方法被标记为virtual
□派生类中有匹配的override方法
如下图所示,显示了一个从virtual Print方法后面开始,并指向override Print方法的箭头
具体示例如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace review 8 { 9 class MyBaseClass //基类 10 { 11 virtual public void Print() 12 { 13 Console.WriteLine("This is the base class."); 14 } 15 } 16 class MyDerivedClass : MyBaseClass //派生类 17 { 18 override public void Print() 19 { 20 Console.WriteLine("This is the derived class."); 21 } 22 } 23 class Program 24 { 25 static void Main(string[] args) 26 { 27 MyDerivedClass derived = new MyDerivedClass(); 28 MyBaseClass mybc = (MyBaseClass)derived; //强制转换成基类 29 derived.Print(); 30 mybc.Print(); 31 Console.Read(); 32 } 33 } 34 } 35 /* 36 * 输出如下: 37 * This is the derived class. 38 * This is the derived class. 39 * */
其他的一些关于virtual和override的信息有:
□覆写和被覆写的方法必须有相同的可访问性。e.g.不能是 被覆写是private 而覆写的是public
□不能覆写static方法或非虚方法
□方法、属性、索引器,以及另一种成员类型事件,都可以被声明为virtual和override
Part2 覆写标记为override的方法:
覆写方法可以在继承的任何层次中出现
□当使用对象基类部分的引用调用一个覆写的方法时,方法的调用被沿派生层次上溯执行,一直到标记为override的方法的最高派生(most-derived)版本。
□如果在更高的派生级别有该方法的其他声明,但没有被标记为override,那么它们不会被调用
以以下实例来说明,其中三个类构成一个继承的层次:
MyBaseClass、MyDerivedClass和SecondDerived。其均包含名称为Print的方法,并带有相同的签名。且分别被标记为virtual、override、 override/new 分别看一下第三个类标记为这两个的结果。
1 class MyBaseClass //基类 2 { 3 virtual public void Print() 4 { 5 Console.WriteLine("This is the base class."); 6 } 7 } 8 class MyDerivedClass : MyBaseClass //派生类 9 { 10 override public void Print() 11 { 12 Console.WriteLine("This is the derived class."); 13 } 14 } 15 class SecondDerived : MyDerivedClass //最高派生类 16 { 17 ...// Given in the following pages 18 }
1.情况1:使用override声明Print
如果把SecondDerived的Print方法声明为override,那么它会覆写方法的全部两个低派生级别的版本,如下图所示,如果一个基类的引用被用于调用Print,它会向上传递通过整个链达到类SecondDerived中的实现。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace review 8 { 9 class MyBaseClass //基类 10 { 11 virtual public void Print() 12 { 13 Console.WriteLine("This is the base class."); 14 } 15 } 16 class MyDerivedClass : MyBaseClass //派生类 17 { 18 override public void Print() 19 { 20 Console.WriteLine("This is the derived class."); 21 } 22 } 23 class SecondDerived : MyDerivedClass //最高派生类 24 { 25 public override void Print() 26 { 27 Console.WriteLine("This is the second derived class."); 28 } 29 } 30 class Program 31 { 32 static void Main(string[] args) 33 { 34 SecondDerived derived = new SecondDerived(); 35 MyBaseClass mybc = (MyBaseClass)derived; //强制转换成基类 36 37 derived.Print(); 38 mybc.Print(); 39 Console.Read(); 40 } 41 } 42 } 43 /* 44 * 输出如下: 45 * This is the second derived class. 46 * This is the second derived class. 47 * */
结果是:无论Print是通过派生类调用还是通过基类调用,都会调用最高派生类中的方法。当通过基类调用时,调用被沿着继承层次向上传递。
2.情况2:使用new声明Print
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace review 8 { 9 class MyBaseClass //基类 10 { 11 virtual public void Print() 12 { 13 Console.WriteLine("This is the base class."); 14 } 15 } 16 class MyDerivedClass : MyBaseClass //派生类 17 { 18 override public void Print() 19 { 20 Console.WriteLine("This is the derived class."); 21 } 22 } 23 class SecondDerived : MyDerivedClass //最高派生类 24 { 25 new public void Print() 26 { 27 Console.WriteLine("This is the second derived class."); 28 } 29 } 30 class Program 31 { 32 static void Main(string[] args) 33 { 34 SecondDerived derived = new SecondDerived(); 35 MyBaseClass mybc = (MyBaseClass)derived; //强制转换成基类 36 37 derived.Print(); 38 mybc.Print(); 39 Console.Read(); 40 } 41 } 42 } 43 /* 44 * 输出如下: 45 * This is the second derived class. 46 * This is the derived class. 47 * */
结果是:当方法Print通过SecondDerived的引用调用时,SecondDerived中的方法被执行,正如所期待的那样。然而,当方法通过MyBaseClass的引用调用时,方法调用只向上传递了一级,到达类MyDerived,在那里它被执行。
本来想使用下列代码进行 virtual -> override -> new ->override 的检验
1 class ThirdDerived : SecondDerived 2 { 3 override public void Print() 4 { 5 Console.WriteLine("This is the third derived class."); 6 } 7 }
然而编译器报错为“ThirdDerived.Print()”: 继承成员“SecondDerived.Print()”未标记为 virtual、abstract 或 override,无法进行重写。
不过,当试验virtual-> override->new ->virtual ->override 时却是可以的,而实际上,这个中间多出的virtual是在对之前的一系列方法进行隐藏,即这个virtual其实应该写作 new virtual。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace review 8 { 9 class MyBaseClass //基类 10 { 11 virtual public void Print() 12 { 13 Console.WriteLine("This is the base class."); 14 } 15 } 16 class MyDerivedClass : MyBaseClass //派生类 17 { 18 override public void Print() 19 { 20 Console.WriteLine("This is the derived class."); 21 } 22 } 23 class SecondDerived : MyDerivedClass //最高派生类 24 { 25 new public void Print() 26 { 27 Console.WriteLine("This is the second derived class."); 28 } 29 } 30 class ThirdDerived : SecondDerived 31 { 32 new virtual public void Print() 33 { 34 } 35 } 36 class FourthDerived : ThirdDerived 37 { 38 override public void Print() 39 { 40 Console.WriteLine("This is the fourth derived class."); 41 } 42 } 43 class Program 44 { 45 static void Main(string[] args) 46 { 47 FourthDerived derived = new FourthDerived(); 48 MyBaseClass mybc = (MyBaseClass)derived; //强制转换成基类 49 50 derived.Print(); 51 mybc.Print(); 52 Console.Read(); 53 } 54 } 55 } 56 /* 57 * 输出如下: 58 * This is the fourth derived class. 59 * This is the derived class. 60 * */
综上,对覆写方法的总结为:
通过某个引用对方法进行调用时,实际执行的是从这里出发,连续的一段override覆写中的最后一个的方法。(中间不可以用virtual隔开)。
Part3 覆盖其他成员类型
以上已经描述了如何在方法上使用virtual/override,事实上,在属性事件以及索引器上也是一样的。e.g.下面的代码演示了名为MyProperty的只读属性,其中使用了virtual/override
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace review 8 { 9 class MyBaseClass //基类 10 { 11 private int _mInt = 5; 12 virtual public int MyProperty 13 { 14 get { return _mInt; } 15 } 16 } 17 class MyDerivedClass : MyBaseClass //派生类 18 { 19 private int _mInt = 10; 20 public override int MyProperty 21 { 22 get 23 { 24 return _mInt; 25 } 26 } 27 } 28 class Program 29 { 30 static void Main(string[] args) 31 { 32 MyDerivedClass derived = new MyDerivedClass(); 33 MyBaseClass mybc = (MyBaseClass)derived; //强制转换成基类 34 35 Console.WriteLine(derived.MyProperty); 36 Console.WriteLine(mybc.MyProperty); 37 Console.Read(); 38 } 39 } 40 } 41 /* 42 * 输出如下: 43 * 10 44 * 10 45 * */
这里需要注意的是,最终执行下去返回的属性就是派生类的属性。
p.s. 使用virtual声明,并不影响方法or属性or事件or索引的执行(字段无法被virtual修饰)。virtual修饰的方法or属性or事件or索引仍可以有函数体。
如下例所示
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace review 8 { 9 class MyBaseClass //基类 10 { 11 private int _mInt = 5; 12 virtual public int MyProperty 13 { 14 get { return _mInt; } 15 } 16 } 17 class Program 18 { 19 static void Main(string[] args) 20 { 21 MyBaseClass mybc = new MyBaseClass(); 22 Console.WriteLine(mybc.MyProperty); 23 Console.Read(); 24 } 25 } 26 } 27 /* 28 * 输出如下: 29 * 5 30 * */
转载于:https://www.cnblogs.com/quintessence/p/9100751.html
review——C# (6)虚方法和覆写方法相关推荐
- [改善Java代码]覆写equals方法必须覆写hashCode方法
覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...
- Java中field的覆写_Java中方法的覆写
[套装4本]java编程思想4第4版+ 402.5元 包邮 (需用券) 去购买 > 一.方法的重写概念 之前说了子类如果继承了一个父类,那么子类就会拥有父类的方法(不包括构.造方法)和属性,此时 ...
- C#中的屏蔽、覆写和抽象
屏蔽基类成员 虽然派生类不能删除其继承的任何成员,但可以声明一个与基类成员签名相同的成员来屏蔽之.(注意方法的签名由名称和参数列表组成,不包括返回值类型) 要让编译器知道你在故意屏蔽继承的成员,可使用 ...
- 子类访问父类和方法覆写
子类不能直接访问父类的私有成员: 但是子类可以调用父类中的非私有方法来间接访问父类的私有成员. Person类中有私有字段name,Student继承Person new Sudent().name; ...
- 08方法重载,覆写,多态
文章目录 重载overload 方法的覆写 多态 定义 实现一个程序 利用多态 优化 如何在子类中调用被覆盖的父类方法 finally修饰词 重载overload 我们在C语言中,函数名就是不同函数的 ...
- 关于java方法的重载(Overloading),覆写(Override)以及final 方法的几点说明
昨天在一个群里面一个群友问道final 方法可不可以重载,我不假思索的说final 方法不能继承不能重载.后来晚上睡不着觉想想总觉得不对头,翻翻书一看自己简直就是胡说八道,才意识到这些基础概念的东西时 ...
- Java中方法的重载(overload)与重写/覆写(override)
重载-Overload 函数的方法参数个数或类型不一致,称为方法的重载. 从含义上说,只要求参数的个数或参数的类型不一致就说两个函数是重载函数,而至于返回值是否一样,没关系.同时,重载可以发生在同一个 ...
- Java面试基础问题之(七)—— 方法的重载 VS 覆写规则
一. Java方法声明的众多属性 在讨论重载和覆写的区别之前,先补充一下Java方法的背景知识,看下面最为常见的main方法声明,为了完整介绍,自行加了异常的抛出: public static vo ...
- 第二节:重写(new)、覆写(overwrite)、和重载(overload)
一. 重写 1. 关键字:new 2. 含义:子类继承父类中的普通方法,如果在子类中重写了一个和父类中完全相同的方法,子类中会报警告(问是否显式的隐藏父类的中的方法),如果在子类中的方法前加上new关 ...
最新文章
- envi反演水质参数_科技前沿基于GOCI静止水色卫星数据的长江口及邻近海域Kd(490)遥感反演及其在机载激光测深预评估中的应用...
- python画图代码彩虹-python绘制彩虹图
- 技术系列课|从0到1 构建实时音视频引擎
- 【CSDN】【从800+CSDN支持的Emoji表情中筛选出文章标题可用的 1️⃣ 2️⃣ 4️⃣ 个表情并进行分类】(文章标题如何使用Emoji表情)⚽️
- mysql innodb flus_MySQL参数解析innodb_flush_neighbors
- 变量详解-----笔记
- mysql初体验学习笔记_MySQL数据库初体验
- Express框架实现原理
- 2020年度中国生命科学十大进展揭晓
- (function($){...})(jQuery) 含义
- easyui datagrid 获得共多少条记录_聊城市优化简化获得电力流程做法在全省供电系统推广...
- 如何用3升和5升桶量取4升水?
- 将pdf拆分成多个pdf
- Python 打怪兽游戏
- 290页11万字数字农业农村项目规划建设方案2022
- hdu多校第六场1005 (hdu6638) Snowy Smilel 线段树/区间最大和
- 聚合器是什么东西?聚合器的可能性
- 四川阆中2021中学高考成绩查询入口,2021年四川高考体检报告结果查询时间及查询网址入口...
- [198].打家劫舍
- 更进阶的实战效率、更准确的研究成果——欢迎参加材料计算PWmat进阶小组会
热门文章
- python详细教程-Python入门教程:超详细1小时学会Python
- python可以干什么-学了Python可以用来干什么呢?
- python简单代码表白-如何正确使用Python进行表白
- 从零开始学习python-从零开始学习python(一)
- python爬虫能干什么-爬虫可以做的事情非常多,Python的爬虫你又了解多少?
- vscode使用教程python-使用VS Code进行Python编程
- 从零开始学python电子书-从零开始学Python程序设计 PDF 完整影印版
- 华为python工程师工资-华为工程师对Python编程的看法
- python 数据分析学什么-python数据分析哪些课程好?
- python程序员在公司都是做什么的-为什么企业很难招聘到好的python程序员?