覆盖与删除之间的区别方法阴影 [英] Difference between Overriding & Method Shadowing

查看:82
本文介绍了覆盖与删除之间的区别方法阴影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,
我看了一篇文章,其中显示了覆盖"和覆盖"之间的区别方法阴影.我试图实现方法屏蔽,但无法实现,因此有人可以帮助我吗?


Hi all,
I have gone through one of the article which shows difference between Overriding & Method Shadowing. I was trying to implement method shadowing but not able to get it so can anybody helps me out ?


class Base
    {
        public void PrintOnScreen()
        {
            Console.WriteLine("Base Method");
        }
    }
    class Derive : Base
    {
        public new void PrintOnScreen()
        {
            Console.WriteLine("Derive Method");
        }
    }
    class MethodShadowingDemo
    {
        public static void Main(string[] args)
        {
            Base objDerive = new Derive();
            objDerive.PrintOnScreen();
            Console.ReadLine();
        }
    }

在此示例中,根据遮罩概念将调用派生类方法,但将其称为基类方法,因此我对该概念的实际工作方式感到有些困惑?

In this example according to shadowing concept derived class method is to be called but instead it''s calling base class method so i am bit confused how the concept actually works ?

推荐答案

这可能有点令人困惑,所以让我们举一个简单的例子:
This can be a bit confusing, so lets have a simple example:
public class A
    {
    public void P() { Console.WriteLine("A:P"); }
    public virtual void Q() { Console.WriteLine("A:Q"); }
    }
public class B : A
    {
    public new void P() { Console.WriteLine("B:P"); }
    public override void Q() { Console.WriteLine("B:Q"); }
    }
class Program
    {
    static void Main(string[] args)
        {
        Console.WriteLine("Started");
        A a = new A();
        B b = new B();
        A r = b;
        a.P();
        a.Q();
        b.P();
        b.Q();
        r.P();
        r.Q();
        Console.WriteLine("Stopped");
        Console.ReadLine();
        }
    }

运行此命令时,我们得到:

When we run this, we get:

Started
A:P
A:Q
B:P
B:Q
A:P
B:Q
Stopped

当我们声明A类型的变量时,即使将派生类的实例分配给它,我们也总是从类A调用"P".我们从实例类型而不是变量类型中调用"Q".
当我们声明类型B的变量时,我们总是从类B调用"P"和"Q".

"P"是一个隐藏方法(阴影是VB的用语,隐藏是C#):仅当您明确引用派生类的成员时,才使用派生类版本.如果通过基类访问它,则将使用基类版本.

"Q"是一个覆盖的方法-对它的任何引用都将使用最派生的类定义,而不是基类.如果不存在这样的定义,它将使用基类定义.

When we declare a variable of type A, we always call "P" from class A, even if we assign an instance of the derived class to it. We call "Q" from the instance type, rather than the variable type.
When we declare a variable of type B, we always call "P" and "Q" from class B.

"P" is a hidden method (shadowed is VB parlance, hidden is C#): The derived class version will be used only if you are explicitly referring to a member of a derived class. If you are accessing it via a base class, the base class version will be used.

"Q" is an overridden method - any reference to it goes to the most derived class definition, rather than the base class. If no such definition exists, it will use the base class definition.


class Base
{
        public void PrintOnScreen()
        {
            Console.WriteLine("Base Method");
        }
}
class Derive : Base
{
        public new void PrintOnScreen()
        {
            Console.WriteLine("Derive Method");
        }
}
class MethodShadowingDemo
{
        public static void Main(string[] args)
        {
            Base objDerive = new Derive();
            objDerive.PrintOnScreen();
            Console.ReadLine();
        }
}


输出为

Base Method

,因为未将基类方法标记为虚方法.如果将其标记为虚拟,并且有任何可重写的方法可用,那么您将获得派生方法"输出.

现在我要更改代码

Because the base class method is not marked as virtual. If it is marked as virtual and if there is any overridable method is available then you will get "Derive Method" output.

Now I am changing the code

class Base
{
        public virtual void PrintOnScreen()
        {
            Console.WriteLine("Base Method");
        }
}
class Derive : Base
{
        public new void PrintOnScreen()
        {
            Console.WriteLine("Derive Method");
        }
}
class MethodShadowingDemo
{
        public static void Main(string[] args)
        {
            Base objDerive = new Derive();
            objDerive.PrintOnScreen();
            Console.ReadLine();
        }
}


仍然会输出


still the output would be

Base Method

,因为即使基类方法也被标记为virtaul,但在派生类中却没有任何可重写的方法.即使从基类方法中删除了"new"关键字.

仅当您将子类函数标记为可重写并且将父类函数标记为virtual时,才将输出作为派生方法".

because even the base class method is marked as virtaul but it doesnot have any overridable method in the derived class. Even if you remove the "new" keyword from the Base class method.

You will get output as "Derive Method" only if you marked child class function as overridable and parent class function as virtual.

class Base
{
        public virtual void PrintOnScreen()
        {
            Console.WriteLine("Base Method");
        }
}
class Derive : Base
{
        public override void PrintOnScreen()
        {
            Console.WriteLine("Derive Method");
        }
}
class MethodShadowingDemo
{
        public static void Main(string[] args)
        {
            Base objDerive = new Derive();
            objDerive.PrintOnScreen();
            Console.ReadLine();
        }
}



希望您现在能理解.



Hope you can understand now.


这些家伙对这个主题很清楚:)竖起大拇指,codeproject越来越好了:D

除此之外,还只是关于为什么以及何时应使用新关键字的一个小观点

好的,回到基础.从类继承时,标记为public或protected的方法将对子类可用.对?因此,在设计时,您决定我可能需要更多的扩展行为或与这些方法不同的行为.让我们举个例子.
These guys were pretty clear about the topic :) Thumbs up, codeproject is getting better by the day :D

In addition to those, just a small point of view on why and when you should use new keyword

Ok, back to the basics. When you inherit from a class, the methods marked with either public or protected will be available to the child class. right? So while designing, you decide that I might need more expanded behavior or different behavior from these methods. Let''s take an example.
public class Bird {
     public void Eat() {
          Console.WriteLine("Eating....");
     }

     public virtual void Fly() {
          Console.WriteLine("Flying....");          
     }
}


几乎没有什么要注意的,因为每只鸟都在吃东西,所以您知道这不会改变,因此您无意改变其在子班级的行为.但是有些鸟不会飞,所以您知道它会发生变化,因此您要使用virtual关键字标记该方法.您可以通过抽象类来实现相同的目的,但这是不同的教训:)

因此,让我们实现2个鸟类


Few things to notice, since every bird is eating, you know that''s not going to change, so you don''t intend to change it''s behavior in child classes. But some birds can''t fly, so you know it''s going to change, so you are marking that method with virtual keyword. You can achieve the same thing, by abstract classes but it''s a different lesson :)

So let''s implement 2 birds classes

public class Robin : Bird {
     public override void Fly() {
          Console.WriteLine("Flying Fast....");
     }
}
public class Ostrich : Bird {
     public override void Fly() {
          Console.WriteLine("Cannot fly");
     }
}


现在,我要做一些疯狂的事情:D笑所有您想要的,但是我不能很快提出一个更好的例子.但我知道它会帮助您理解概念.

因此,让我们想象一下,您想包括不能进食的残疾鸟类.现在,这在原始设计中是无法预期的. IE.它不是设计中想要的.因此,您可以返回到原始设计并使用override装饰Eat()方法.

但是,当您使用别人的代码时,这是不可能的. IE.您没有源代码来编辑和更新,而只有编译的DLL.那么现在怎么办?这就是new关键字可以帮助您的地方.


Now, I am going do something crazy :D Laugh all you want, but I could not come up with a better example this quickly. But I know it''ll help you understand the concept.

So let''s imagine, you are want to include disabled birds who can''t eat. Now this was not expected in the original design. I.e. it was not intended in the design. So you can go back to the original design and decorate the Eat() method with override.

But this is not possible when you are using someone else''s code. I.e. you don''t have the source code to edit and update but only the compiled DLL. So now what? That''s where new keyword helps you out.

public class DisabledBird : Bird {
     public override void Fly() {
          Console.WriteLine("Cannot fly :(");
     }

     public new void Eat() {
          Console.WriteLine("Cannot eat :(");
     }
}


new关键字有两个用途.
1.允许您隐藏父类的方法,并为同一签名实现不同的方法.
2.允许您跟踪自己执行过的方法.这样一来,当您稍后查看代码时,它就不会使您感到困惑.

注意:这并不意味着您不应该设计代码或忽略覆盖即可.如果这样做,您将很快失去维护代码的能力.仅在特殊情况下(例如,在使用工具箱或库时)才应使用此方法.

该死的,这真是一篇文章:P Apologies

希望对您有所帮助:)问候


The new keyword serves 2 purposes.
1. Allows you to hide methods of parent classes and implement a different method for the same signature.
2. Allows you to keep track of methods that you did like that. So that it would not confuse you when you look in to the code later on.

NOTE: This is NOT mean that you should not design your code or overriding can be just ignored. If you do that, you''ll quickly lose the ability to maintain your code. This should be only used for exceptional cases like when you are using a toolkit or a library.

Damn, this turned out to be an article :P Apologies

Hope this helps :) Regards


这篇关于覆盖与删除之间的区别方法阴影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆