简体   繁体   English

重载继承类中的方法

[英]Overloading methods in inherited classes

I have started to understand that I do not understand what is going on. 我已经开始明白,我不明白发生了什么。 There is the following behavior in C#: C#中存在以下行为:

public class Base
{
    public void Method(D a)
    {
        Console.WriteLine("public void Method(D a)");
    }
}

public class Derived: Base
{
    public void Method(B a)
    {
        Console.WriteLine("public void Method(B a)");
    }
}

public class B { }

public class D: B { }

class Program
{
    static void Main(string[] args)
    {
        Derived derived = new Derived();
        D d = new D();

        derived.Method(d);
    }
}

It will print 它会打印出来

public void Method(B a)

instead of 代替

public void Method(D a)

It's surprising. 这令人惊讶。 I suppose that the reason of this behavior is implementation of methods table. 我想这种行为的原因是方法表的实现。 CLR does not search methods in the base class if it finds the corresponding method in the current type. 如果CLR在当前类型中找到相应的方法,则它不会搜索基类中的方法。 I think they were trying to improve performance. 我认为他们正在努力提高绩效。

But I was completely disappointed with the following code: 但我对以下代码完全失望:

public class Base
{
    public virtual void Method(D a)
    {
        Console.WriteLine("public void Method(D a)");
    }
}

public class Derived: Base
{
    public override void Method(D a)
    {
        Console.WriteLine("public override void Method(D a)");
    }

    public void Method(B a)
    {
        Console.WriteLine("public void Method(B a)");
    }

}

public class B { }

public class D: B { }

class Program
{
    static void Main(string[] args)
    {
        Derived derived = new Derived();
        D d = new D();

        derived.Method(d);
    }
}

and it will print 它会打印出来

public void Method(B a)

instead of 代替

public override void Method(D a)

It's awful and very unpredictable. 这太糟糕了,非常不可预测。

Can anyone explain it? 有人能解释一下吗?

I suppose that the method table has methods that have been implemented in the current type only (excluding overriding methods) and CLR stops looking for the corresponding method as soon as any method that can be called is found. 我想方法表只有在当前类型中实现的方法(不包括重写方法),并且只要找到任何可以调用的方法,CLR就会停止查找相应的方法。 Am I right? 我对吗?

I have started to understand that I do not understand what is going on. 我已经开始明白,我不明白发生了什么。

Thus begins wisdom. 从而开始智慧。

It's awful and very unpredictable. 这太糟糕了,非常不可预测。

It is neither. 它既不是。 By contrast, the feature is designed to reduce unpredictability by eliminating a cause of the brittle base class failure. 相比之下,该功能旨在通过消除脆性基类故障的原因减少不可预测性

Can anyone explain it? 有人能解释一下吗?

See my 2007 article on the subject. 请参阅我2007年关于此主题的文章。

https://blogs.msdn.microsoft.com/ericlippert/2007/09/04/future-breaking-changes-part-three/ https://blogs.msdn.microsoft.com/ericlippert/2007/09/04/future-breaking-changes-part-three/

The short version though is: a method in a derived class is always better than a method in a base class; 简短的版本是:派生类中的方法总是比基类中的方法更好; the person who wrote the derived class knows more about the object semantics and is handling a more specific case than the person who wrote the base class. 编写派生类的人更多地了解对象语义 ,并且处理比编写基类的人更具体的情况

Servy points out that I did not cover your second point. Servy指出我没有报道你的第二点。 Why does the override in the derived class not make the "D" method "in the derived class"? 为什么派生类中的覆盖不会使“D”方法“在派生类中”?

Virtual methods are considered to be methods of the class where they were declared , not of the class where they were most recently overridden . 虚方法被认为是声明它们的类的方法,而不是它们最近被覆盖的类的方法 Why? 为什么? Because choosing to override or not is an implementation detail of a class , and not part of the public surface area. 因为选择是否覆盖是类的实现细节 ,而不是公共表面区域的一部分。

I mean, think about it. 我想说的是,考虑一下。 You write some code, it works, and then you say, hey, I'm going to make a new (or remove an old!) override of this method somewhere in this type hierarchy, and suddenly that changes overload resolution somewhere else? 你写了一些代码,它可以工作,然后你说,嘿,我将在这个类型层次结构的某个地方创建一个新的(或删除旧的!)覆盖此方法,并突然在其他地方更改重载决策? That is exactly the sort of brittleness that C# seeks to eliminate. 这正是C#试图消除的那种脆弱性。

Remember, C# was very carefully designed for a world in which code is being edited by teams of people . 请记住,C#经过精心设计, 适用于人员编辑代码的世界 Many modern languages were, bizarrely, designed as though one person was writing all the code and they got it right the first time; 奇怪的是,许多现代语言被设计成好像一个人正在编写所有代码并且他们第一次就做对了; that's not realistic. 那是不现实的。 Some of the more unusual features of C#, like the one you've discovered, are there to help you keep your program behaviour predictable even as other people are editing your base classes. C#的一些更不寻常的功能,就像你发现的一样,可以帮助你保持程序行为的可预测性,即使其他人正在编辑你的基类。

I can see the confusion here. 我可以在这看到混乱。 Eric's answer could be better illustrated with an example. 通过一个例子可以更好地说明Eric的答案。 If you changed the code as follows... 如果您更改了以下代码...

public class Base
{
    public virtual void Method(D a)
    {
        Console.WriteLine("public void Method(D a)");
    }

    public void Method(B a)
    {
        Console.WriteLine("public void Method(B a)");
    }
}

public class Derived : Base
{
    public override void Method(D a)
    {
        Console.WriteLine("public override void Method(D a)");
    }

}

public class B { }

public class D : B { }

The output becomes "public override void Method(D a)". 输出变为“public override void Method(D a)”。

Why? 为什么?

As stated in Eric's article... 如Eric的文章中所述......

methods in a base class are not candidates if any method in a derived class is applicable 如果派生类中的任何方法适用,则基类中的方法不是候选方法

As both Method(D) and Method(B) are now in the base class, Method(D) has become the closest match which is overrided in your derived class hence the output. 由于方法(D)和方法(B)现在都在基类中,因此方法(D)已成为最接近的匹配,它在派生类中被覆盖,因此输出。

Pretty confusing for a newbie hey? 对新手来说相当困惑嘿? Well pretty confusing for an experienced developer also. 对于经验丰富的开发人员来说也很困惑。 I think the key point to make here is that what you have here is bad design, I'm not talking about the CLR or C# compiler, it's done the best it can do to help you out here, I'm talking about the classes in your example. 我认为这里要做的关键点是你在这里有什么不好的设计,我不是在谈论CLR或C#编译器,它做得最好它可以帮助你在这里,我在谈论类在你的例子中。

I think a common mistake made by many people new to OOP is to overuse the new toy that is inheritance. 我认为很多人对OOP不熟悉的一个常见错误就是过度使用继承的新玩具。 Inheritance is often not the favoured relationship used in OOD. 继承通常不是OOD中使用的优惠关系。 When you start studying OOP design patterns you'll note that many of the patterns do not use inheritance. 当您开始研究OOP设计模式时,您会注意到许多模式不使用继承。

Why? 为什么? Because your example illustrates the sort of confusion that can be created when using inheritance, it is known as Fragile Inheritance . 因为您的示例说明了在使用继承时可以创建的混淆,所以它被称为脆弱继承 Design patterns more often use aggregation and composition to divide up a problem space into a more workable, extensible and manageable solution. 设计模式更经常使用聚合和组合将问题空间划分为更可行,可扩展和可管理的解决方案。

Inheritance is a powerful construct, as with most powerful things, it should be used sparingly and with care. 继承是一种强大的结构,与大多数强大的东西一样,它应该谨慎使用并谨慎使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM