总结virtual override sealed new在方法上的应用
对于方法(属性、事件)
1. 如想重写(扩展和修改继承)方法要求有两个
a. 基类必须是virtual
b. 继承类型的同签名方法必须override
也就是说基类和继承类都必须同意,重写才能实现
2. 刚才只是说了只继承了一层的情况,但如果有多层集成,比如CClass:BClass:AClass
a. B中的某个方法M1是override A中的M1来的,这时如果C再重写M1的时候,就不要求B的M1有virtual关键字修饰了。重写(override)来的方法,默认也同意被其子类override(即便没有virtual其实也不能有virtual)。
b. 当然如果不同意其子类重写这个方法也可以,override的时候加上sealed。
3. 如果子类主动不想跟父类的同名方法有什么瓜葛,不带override就可以了,但是这样编译器会给个警告,如果不想看警告可以new一下,主动声明跟父类没啥瓜葛。
a) new的方法默认是不能被其子类重写的
b) new可以跟virtual合伙,表明欢迎子类重写这个方法(只有virtual也可以,多个编译警告)
c) 只要跟父类有同签名方法new就可以存在,不论父类是否允许他的方法被重载
4. 除了virtual还有abstract关键字,abstract比virtual还彻底,基类干脆就不实现任何功能了,就等着子类来override,所以abstract肯定也是同意做被派生类重载的。
总结几种方法的修饰组合及其结果
virtual:同意被重载
abstract:本方法没内容,派生类一定要记得重载我哦,除非派生类也是抽象的
override:同意重载父类的同名方法 也同意被自己的子类重载
override sealed:同意重载父类 但不同意被自己的子类重载(sealed只是配合override的,自己不会单独跑出来)
什么修饰都没有:不同意重载父类 也不同意子类重载自己
new:特此声明,父类的同名方法跟我无关
virtual new:父类同名方法跟我无关,不过欢迎子类重载我
样例
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Example03
{
class Program
{
static void Main(string[] args)
{
AClass a = new CClass();
a.M1();
a.M2();
a.M3();
a.M4();
a.M5();
a.M6();
a.M7();
a.M8();
Console.WriteLine("-");
BClass b = new CClass();
b.M1();
b.M2();
b.M3();
b.M4();
b.M5();
b.M6();
b.M7();
b.M8();
Console.ReadLine();
}
}
public class CClass : BClass
{
public override void M1()
{
Console.WriteLine("C.M1");
}
public new void M2()
{
Console.WriteLine("C.M2");
}
public void M3()//(有编译警告)
{
Console.WriteLine("C.M3");
}
public new void M4()
{
Console.WriteLine("C.M4");
}
public override void M5()
{
Console.WriteLine("C.M5");
}
public new void M6()
{
Console.WriteLine("C.M6");
}
public new void M7()
{
Console.WriteLine("C.M7");
}
public new void M8()
{
Console.WriteLine("C.M7");
}
}
public abstract class BClass : AClass
{
public override void M1()//重写父类 允许子类重写自己
{
Console.WriteLine("B.M1");
}
public override void M2()//重写父类 允许子类重写自己
{
Console.WriteLine("B.M2");
}
public override void M3()//重写父类 允许子类重写自己
{
Console.WriteLine("B.M3");
}
public new void M4()//不重写父类 不允许子类重写自己
{
Console.WriteLine("B.M4");
}
public new virtual void M5()//不重写父类 允许子类重写自己
{
Console.WriteLine("B.M5");
}
public new virtual void M6()//不重写父类 允许子类重写自己
{
Console.WriteLine("B.M6");
}
public override sealed void M7()//重写父类 不允许子类重写自己
{
Console.WriteLine("B.M7");
}
public virtual void M8()//不重写父类 允许子类重写自己(有编译警告)
{
Console.WriteLine("B.M8");
}
}
public class AClass
{
public virtual void M1()
{
Console.WriteLine("A.M1");
}
public virtual void M2()
{
Console.WriteLine("A.M2");
}
public virtual void M3()
{
Console.WriteLine("A.M3");
}
public virtual void M4()
{
Console.WriteLine("A.M4");
}
public virtual void M5()
{
Console.WriteLine("A.M5");
}
public virtual void M6()
{
Console.WriteLine("A.M6");
}
public virtual void M7()
{
Console.WriteLine("A.M7");
}
public virtual void M8()
{
Console.WriteLine("A.M8");
}
}
}
B.M2
B.M3
A.M4
A.M5
A.M6
B.M7
A.M8
-
C.M1
B.M2
B.M3
B.M4
C.M5
B.M6
B.M7
B.M8
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?