继承中的重载方法 类
Overloading methods in inherited classes
我已经开始明白我不明白是怎么回事了。在 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);
}
}
它将打印
public void Method(B a)
而不是
public void Method(D a)
令人惊讶。我想这种行为的原因是方法 table 的实现。如果 CLR 在当前类型中找到相应的方法,则不会在基 class 中搜索方法。我认为他们正在努力提高性能。
但是我对下面的代码完全失望了:
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);
}
}
它将打印
public void Method(B a)
而不是
public override void Method(D a)
这很糟糕而且非常不可预测table。
谁能解释一下?
我假设方法table有只在当前类型中实现的方法(不包括覆盖方法),一旦找到任何可以调用的方法,CLR就会停止寻找相应的方法.我说得对吗?
I have started to understand that I do not understand what is going on.
智慧由此开始。
It's awful and very unpredictable.
两者都不是。相比之下,该功能旨在通过 消除脆性基础 class 失败的原因来 减少 不可预测性。
Can anyone explain it?
请参阅我 2007 年关于该主题的文章。
https://blogs.msdn.microsoft.com/ericlippert/2007/09/04/future-breaking-changes-part-three/
虽然简短的版本是:派生 class 中的方法总是比基 class 中的方法好;编写派生 class 的人比编写基地 class.
Servy 指出我没有涵盖您的第二点。为什么派生 class 中的覆盖不会使 "D" 方法 "in the derived class"?
虚拟方法被认为是声明它们的 class 的 方法 ,而不是声明它们的 class 的 方法最近被覆盖。为什么?因为 选择覆盖与否是 class 的实现细节,而不是 public 表面区域的一部分。
我的意思是,考虑一下。你写了一些代码,它起作用了,然后你说,嘿,我要在这个类型层次结构中某处重写这个方法,突然改变 过载分辨率 到其他地方?这正是 C# 试图消除的那种脆弱性。
请记住,C# 是为 一个代码由团队编辑的世界 精心设计的。奇怪的是,许多现代语言的设计就好像一个人在编写所有代码,而且他们一次就把它弄对了;那是不现实的。 C# 的一些更不寻常的功能,例如您发现的功能,可以帮助您保持程序行为可预测,即使其他人正在编辑您的基础 classes。
我可以看出这里的混乱。埃里克的回答可以用一个例子来更好地说明。如果您按如下方式更改代码...
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 { }
输出变为"public override void Method(D a)"。
为什么?
如 Eric 的文章所述...
methods in a base class are not candidates if any method in a derived
class is applicable
由于 Method(D) 和 Method(B) 现在都在基础 class 中,Method(D) 已成为最接近的匹配项,它在派生的 class 中被覆盖,因此输出.
对新手来说很混乱吗?对于有经验的开发人员来说,这也很令人困惑。我认为这里要说明的关键是你这里的设计不好,我不是在谈论 CLR 或 C# 编译器,它已经尽力帮助你了,我在谈论 class在你的例子中。
我认为许多刚接触 OOP 的人常犯的一个错误是过度使用继承这一新玩具。继承通常不是 OOD 中使用的首选关系。当您开始研究 OOP 设计模式时,您会注意到许多模式不使用继承。
为什么?因为您的示例说明了使用继承时可能造成的混淆,所以它被称为 Fragile Inheritance。设计模式更经常使用聚合和组合将问题 space 分解为更可行、更可扩展和更易于管理的解决方案。
继承是一种强大的结构,与最强大的事物一样,应谨慎使用。
我已经开始明白我不明白是怎么回事了。在 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);
}
}
它将打印
public void Method(B a)
而不是
public void Method(D a)
令人惊讶。我想这种行为的原因是方法 table 的实现。如果 CLR 在当前类型中找到相应的方法,则不会在基 class 中搜索方法。我认为他们正在努力提高性能。
但是我对下面的代码完全失望了:
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);
}
}
它将打印
public void Method(B a)
而不是
public override void Method(D a)
这很糟糕而且非常不可预测table。
谁能解释一下?
我假设方法table有只在当前类型中实现的方法(不包括覆盖方法),一旦找到任何可以调用的方法,CLR就会停止寻找相应的方法.我说得对吗?
I have started to understand that I do not understand what is going on.
智慧由此开始。
It's awful and very unpredictable.
两者都不是。相比之下,该功能旨在通过 消除脆性基础 class 失败的原因来 减少 不可预测性。
Can anyone explain it?
请参阅我 2007 年关于该主题的文章。
https://blogs.msdn.microsoft.com/ericlippert/2007/09/04/future-breaking-changes-part-three/
虽然简短的版本是:派生 class 中的方法总是比基 class 中的方法好;编写派生 class 的人比编写基地 class.
Servy 指出我没有涵盖您的第二点。为什么派生 class 中的覆盖不会使 "D" 方法 "in the derived class"?
虚拟方法被认为是声明它们的 class 的 方法 ,而不是声明它们的 class 的 方法最近被覆盖。为什么?因为 选择覆盖与否是 class 的实现细节,而不是 public 表面区域的一部分。
我的意思是,考虑一下。你写了一些代码,它起作用了,然后你说,嘿,我要在这个类型层次结构中某处重写这个方法,突然改变 过载分辨率 到其他地方?这正是 C# 试图消除的那种脆弱性。
请记住,C# 是为 一个代码由团队编辑的世界 精心设计的。奇怪的是,许多现代语言的设计就好像一个人在编写所有代码,而且他们一次就把它弄对了;那是不现实的。 C# 的一些更不寻常的功能,例如您发现的功能,可以帮助您保持程序行为可预测,即使其他人正在编辑您的基础 classes。
我可以看出这里的混乱。埃里克的回答可以用一个例子来更好地说明。如果您按如下方式更改代码...
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 { }
输出变为"public override void Method(D a)"。
为什么?
如 Eric 的文章所述...
methods in a base class are not candidates if any method in a derived class is applicable
由于 Method(D) 和 Method(B) 现在都在基础 class 中,Method(D) 已成为最接近的匹配项,它在派生的 class 中被覆盖,因此输出.
对新手来说很混乱吗?对于有经验的开发人员来说,这也很令人困惑。我认为这里要说明的关键是你这里的设计不好,我不是在谈论 CLR 或 C# 编译器,它已经尽力帮助你了,我在谈论 class在你的例子中。
我认为许多刚接触 OOP 的人常犯的一个错误是过度使用继承这一新玩具。继承通常不是 OOD 中使用的首选关系。当您开始研究 OOP 设计模式时,您会注意到许多模式不使用继承。
为什么?因为您的示例说明了使用继承时可能造成的混淆,所以它被称为 Fragile Inheritance。设计模式更经常使用聚合和组合将问题 space 分解为更可行、更可扩展和更易于管理的解决方案。
继承是一种强大的结构,与最强大的事物一样,应谨慎使用。