Exact difference between overriding and hiding
任何人都能从记忆和参考的角度来判断重写和隐藏的工作原理吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class A { public virtual void Test1() { //Impl 1} public virtual void Test2() { //Impl 2} } class B : A { public override void Test1() { //Impl 3} public new void Test2() { Impl 4} } static Main() { A aa=new B() //This will give memory to B aa.Test1(); //What happens in terms of memory when this executes aa.Test2(); //-----------------------SAME------------------------ } |
这里内存与类B有关,但是在第二条语句中,将调用aa.test2类A的方法。为什么会这样?如果B有内存,那么应该调用B的方法(在我看来)。
任何一个非常深入和完整地描述这个基本原理的链接/练习都将是一个很大的帮助。
看看埃里克·利珀特的另一个问题的答案。
为了解释(在我的理解范围内),这些方法进入"槽"。
由于
相比之下,由于
要添加到@rawling的答案中,可以使用如下示例显示实际示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Base { // base property public virtual string Name { get { return"Base"; } } } class Overriden : Base { // overriden property public override string Name { get { return"Overriden"; } } } class New : Base { // new property, hides the base property public new string Name { get { return"New"; } } } |
1。压倒一切
在overriden属性的情况下,基类的虚方法槽将被另一个实现替换。编译器将该方法视为虚拟的,并且必须在运行时使用对象的虚拟表解析其实现。
1 2 3 4 5 6 7 8 9 10 11 12 | { Base b = new Base(); Console.WriteLine(b.Name); // prints"Base" b = new Overriden(); // Base.Name is virtual, so the vtable determines its implementation Console.WriteLine(b.Name); // prints"Overriden" Overriden o = new Overriden(); // Overriden.Name is virtual, so the vtable determines its implementation Console.WriteLine(o.Name); // prints"Overriden" } |
2。躲藏
当使用
如果变量的类型是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { Base b = new Base(); Console.WriteLine(b.Name); // prints"Base" b = new New(); // type of `b` variable is `Base`, and `Base.Name` is virtual, // so compiler resolves its implementation through the virtual table Console.WriteLine(b.Name); // prints"Base" New n = new New(); // type of `n` variable is `New`, and `New.Name` is not virtual, // so compiler sees `n.Name` as a completely different property Console.WriteLine(n.Name); // prints"New" } |
三。总结
如果代码的一部分接受基类型,它将在运行时始终使用虚拟表。对于大多数OOP场景,这意味着将一个方法标记为
4。实例化后的对象大小
注意,实例化这些类型中的任何一个都不会创建虚拟表的副本。每个.NET对象都有几个字节的头和指向其类型表(
对于
已经在这里回答了
重写是对同一方法签名的多个可能实现的定义,这样实现就由第零个参数的运行时类型(通常由C中的名称标识)决定。
隐藏是派生类型中方法的定义,其签名与它的一个基类型中的签名相同,但不进行重写。
覆盖和隐藏的实际区别如下:
隐藏适用于所有其他成员(静态方法、实例成员、静态成员)。它基于早期绑定。更清楚地说,要调用或使用的方法或成员是在编译时确定的。
?如果方法被重写,则要调用的实现基于此参数的运行时类型。?如果方法只是隐藏的,则要调用的实现基于参数this的编译时类型。
以下是一些示例:示例1。例2
类A中的test1()方法和类B中的test1()方法将根据methodoverriding执行。
类A中的test2()方法和类B中的test2()方法将根据方法隐藏执行。
在重写方法中,将执行子类成员,在隐藏方法中,将执行父类成员。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | class Base { int a; public void Addition() { Console.WriteLine("Addition Base"); } public virtual void Multiply() { Console.WriteLine("Multiply Base"); } public void Divide() { Console.WriteLine("Divide Base"); } } class Child : Base { new public void Addition() { Console.WriteLine("Addition Child"); } public override void Multiply() { Console.WriteLine("Multiply Child"); } new public void Divide() { Console.WriteLine("Divide Child"); } } class Program { static void Main(string[] args) { Child c = new Child(); c.Addition(); c.Multiply(); c.Divide(); Base b = new Child(); b.Addition(); b.Multiply(); b.Divide(); b = new Base(); b.Addition(); b.Multiply(); b.Divide(); } } |
输出:
加法儿童
乘法儿童
分裂儿童
加碱
乘法儿童
分基
加碱
乘法基数
分基
在重写时,编译器检查类的对象,但在在隐藏编译器时,只检查类的引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class BaseClass { public void PrintMethod() { Console.WriteLine("Calling base class method"); } } public class ChildClass { public new void PrintMethod() { Console.WriteLine("Calling the child or derived class method"); } } class Program { static void Main() { BaseClass bc = new ChildClass(); bc.PrintMethod(); } } |
方法隐藏是指当基类引用变量指向子类对象时。它将调用基类中的隐藏方法。
其中,当我们在基类中声明虚方法时。我们在派生类或子类中重写该方法。然后,基类引用变量将调用派生类方法。这称为方法重写。
通过隐藏一个方法或一个属性,您只需声明当您有一个该类型的对象时,您希望停止这种方法的多态性。另外,隐藏方法是以非多态方式调用的,因此在编译时必须知道调用这些方法的类型,因为它只是一个简单的非虚拟方法。
简单地说,重写方法或属性时,重写方法必须与基方法具有相同的签名。当不需要隐藏时,新对象可以采用如下所示的任何形式
1 2 3 4 5 6 7 8 9 | // base public int GrossAmount { get; set; } // hiding base public new string GrossAmount { get; set; } |
从提供的代码中扣除,您应该有
您可以隐藏一个方法,以防需要创建自己的基类(say)方法的实现,而该方法不能被重写,因为,例如,它不是
在我生命的最后阶段,我主要是为了江户的目的而躲藏。
例如,当我不知道谁设置了某个第三个prt
- 从组件创建子类
- 使用
new 关键字隐藏感兴趣的属性 - 把断点放在
set 中 - 等它被击中。
有时非常有用,可以帮助我快速获取信息,尤其是在学习新的