浅析C#中new、override、virtual关键字的区别
Virtual :
virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。
默认情况下,方法是非虚拟的。不能重写非虚方法。
virtual 修饰符不能与 static、abstract, private 或 override 修饰符一起使用。
Override :
override 方法提供从基类继承的成员的新实现。
由 override 声明重写的方法称为重写基方法。重写的基方法必须与 override 方法具有相同的签名。
重写的基方法必须是vitural,override,abstract类型的 ,不能重写非虚方法或是静态方法。
所以override不能与vitural,new,static同时使用。
override 属性,声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是 virtual、abstract 或 override 的。(注意:这里是属性,不是字段,字段是不能被重写的)。
New :
用于创建对象和调用构造函数。
使用 new 修饰符可以显式隐藏从基类继承的成员。
若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。
//下面用代码来说明: //By Alan Liao 2008-10-22
class Father
{
protected string firstname;
protected string lastname; public Father()
{
}
public Father(string firstname, string lastname)
{
this.firstname = firstname;
this.lastname = lastname;
}
public virtual void GetFullName()
{
Console.WriteLine("Father:{0} {1}", firstname, lastname);
}
}
class Son : Father
{
public int age;
public Son() : base() { }
public Son(string firstname, string lastname,int age):base(firstname,lastname)
{
this.age = age;
}
//public new void GetFullName()
public override void GetFullName()
{
Console.WriteLine("Son:{0} {1}", firstname, lastname);
}
}
class Program
{
static void Main(string[] args)
{
Father father = new Father("Alan", "Liao");
Father son1 = new Son("Little Alan ", "Liao",);
father.GetFullName();
son1.GetFullName();
Console.ReadLine();
}
}
本代码输出:
Father:Alan Liao
Son:Little Alan Liao
若将36行换成35行(即将Override换成New)
输出结果为:
(其实代码中的virtual,override 都可以去掉,可以编译,运行通过,但是会有Warnning,结果同下)
Father:Alan Liao
Father:Little Alan Liao
可见结果不一样。
Father a=new Son();
使用new声明的方法使用的仍是父类方法,而override声明的方法使用的是子类中的方法。
其实,根本原因是对象a会优先调用子类中的方法,如果子类没有重写父类的方法,a 就调用父类中的方法。
override 说明的是虚方法,在子类中覆盖父类中的方法。
new则不是,new是给子类新增加了一个函数,可以说除了函数名字相同以外,它跟基类里面的这个同名函数没有任何关系。相当于重新新建了一个方法,从而隐藏了父类方法.
其它:
在 C# 中,派生类可以包含与基类方法同名的方法。
(1)基类方法必须定义为 virtual。
(2)如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,
该方法将有如存在 new 关键字一样执行操作。
(3)如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。
(4)如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。
(5)可以从派生类中使用 base 关键字调用基类方法。
(6) override、virtual 和 new 关键字还可以用于属性、索引器和事件中。
补充:
class Father
{
public virtual void PrintName()
{
Console.WriteLine("Father:{0}", this.GetType().ToString());
}
}
class Son : Father
{
//public new void PrintName()
public override void PrintName()
{
Console.WriteLine("Son:{0}", this.GetType().ToString());
}
}
class Program
{
static void Main(string[] args)
{
Father father = new Father();
Father son = new Son();
father.PrintName();
son.PrintName();
Console.ReadLine();
}
}
以上程序的运行结果:(其中myNamespace是这两个类的命名空间)
Father:myNamespace.Father
Son:myNamespace.Son
如果在第11行将override换成new,那么运行结果如下:
Father:myNamespace.Father
Father:myNamespace.Son
从上可以看出虽然调用的是Father类中的方法,但是this.GetType()返回的是myNamespace.Son类型,所以在Father中的PrintName()方法中的this指的是调用该方法的对象,而不是定义该方法的对象。
浅析C#中new、override、virtual关键字的区别的更多相关文章
- 数据库中in和exists关键字的区别
数据库中in和exists关键字的区别 in 是把外表和内表作hash join,而exists是对外表作loop,每次loop再对内表进行查询. 一直以来认为exists比in效率高的说法是不准确的 ...
- nginx中root与alias关键字的区别
前言 近段时间秋招上岸了,于是每天疯狂补各种分布式基础,每天都在痛苦与快乐中度过. 在学习 nginx 的时候,遇到配置上的问题:root 与 alias 的区别,卡了大概三个小时,记录下来警醒自己不 ...
- Abstract和Virtual和interface , 派生类中重写 override / new关键字
http://www.cnblogs.com/blsong/archive/2010/08/12/1798064.html C#中Abstract和Virtual 在C#的学习中,容易混淆virtua ...
- 【Java_基础】java中static与final关键字的区别
1.static关键字 经static关键字修饰的成员被该类的所有对象所共享,任意一对象对静态变量的修改其它对象都是可见的.通常通过类名来引用static成员.类加载的连接阶段将会为静态成员变量在jv ...
- Java 中 static 和 volatile 关键字的区别?
static指的是类的静态成员,实例间共享 volatile跟Java的内存模型有关,线程执行时会将变量从主内存加载到线程工作内存,建立一个副本,在某个时刻写回.valatile指的每次都读取主内存的 ...
- C++ 类的多态一(virtual关键字--构造函数深刻理解)
//virtual关键字--构造函数深刻理解 #include<iostream> using namespace std; /* C语言编译器,c++编译器全部是静态链编,就是一段一段代 ...
- HTML5中的article和section的区别
HTML5中的article和section的区别 一.总结 一句话总结: article和section都相当于语义化后的div,article强调独立性,section强调分段或者分块 1.art ...
- 浅析c++中virtual关键字
http://blog.csdn.net/djh512/article/details/8973606 1.virtual关键字主要是什么作用? c++中的函数调用默认不适用动态绑定.要触发动态绑定, ...
- sealed,new,virtual,abstract与override关键字的区别?
1. sealed——“断子绝孙” 密封类不能被继承.密封方法可以重写基类中的方法,但其本身不能在任何派生类中进一步重写.当应用于方法或属性时,sealed修饰符必须始终与override一起使用. ...
随机推荐
- 2017-12-09 JavaScript实现ZLOGO子集: 测试用例
续前文JavaScript实现ZLOGO子集: 前进+转向. 在添加新功能之前, 先添加测试用例, 以应对日益复杂的代码. 选择使用QUnit编写运行测试用例. 暂时对比较复杂和I/O无关的部分进行测 ...
- 阿里云或本地部署服务器(一)---nginx本地和服务器代理
具体步骤: 1.nginx下载 2.在G:\nginx-1.15.8\conf/nginx.conf改三处路径:nginx.conf 文件中配置的路径和端口要映射到vue项目工程 a.改 映射端口: ...
- 关于'selffilter' is not a registered tag library. Must be one of:
报错代码: 'selffilter' is not a registered tag library. Must be one of: admin_list admin_modify admin_st ...
- JVM内存结构/JVM运行时数据区,以及堆内存的划分
1.程序计数器: 程序计数器是线程私有的内存,JVM多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,当线程切换后需要恢复到正确的执 行位置(处理器)时,就是通过程序计数器来实现的.此内存区域 ...
- 【XSS】对抗蠕虫 —— 如何让按钮不被 JS 自动点击
前言 XSS 自动点按钮有什么危害? 在社交网络里,很多操作都是通过点击按钮发起的,例如发表留言.假如留言系统有 XSS,用户中招后除了基本攻击外,还能进行传播 -- XSS 自动填入留言内容,并模拟 ...
- shell if条件判断中:双中括号与单中括号的区别
电脑重装了系统,登录虚拟机的shell脚本需重写,在为编写的脚本命名时发现存在同名脚本,才想起来是连接公司服务器的登录脚本,不想写俩脚本,怕记混了,那就整合一下.代码如下: #!/bin/bash#z ...
- ASP.NET Core Web API 集成测试中使用 Bearer Token
在 ASP.NET Core Web API 集成测试一文中, 我介绍了ASP.NET Core Web API的集成测试. 在那里我使用了测试专用的Startup类, 里面的配置和开发时有一些区别, ...
- vue和mpvue
一.mixins的理解 vue中提供了一种混合机制--mixins,用来更高效的实现组件内容的复用.最开始我一度认为这个和组件好像没啥区别..后来发现错了.下面我们来看看mixins和普通情况 ...
- Asp.Net Core 轻松学-利用文件监视进行快速测试开发
前言 在进行 Asp.Net Core 应用程序开发过程中,通常的做法是先把业务代码开发完成,然后建立单元测试,最后进入本地系统集成测试:在这个过程中,程序员的大部分时间几乎都花费在开发.运行 ...
- 是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。
看了 Pivotal 公司的发展历史,这尼玛就是一场商业大片呀. 我们刚开始学习 Spring Boot 的时候肯定都会看到这么一句话: Spring Boot 是由 Pivotal 团队提供的全新框 ...