【问题标题】:What scenarios does it make sense to use "method hiding"? [duplicate]使用“方法隐藏”在哪些场景下有意义? [复制]
【发布时间】:2013-01-22 15:10:20
【问题描述】:

可能重复:
method hiding in c# with a valid example .why is it implemented in the framework.? what is the Real world advantage.?

我想知道方法隐藏在 c# 中如何有用?如果你深入了解这个概念,你会发现方法隐藏是一件令人困惑的事情,并驱使我们采用意大利面条代码风格。其中有一些原因:

1-如果您在派生类中需要一个新方法,您可以在派生类中定义一个具有新名称的新方法。

2-以多态方式使用向上转换时,将无法实现预期的行为,这可能会造成混淆。

(特别是如果基类和派生类位于不同的库中并且您希望在代码中的某个位置对它们进行多态使用,那么这种奇怪的行为可能会非常明显和明显)

class Base
{  
    public void Method() { Console.WriteLine("I am Base Class"); }
}
class Derived: Base
{
    public new void Method() { Console.WriteLine("I am Derived Class");}
}
class Program
{
    static void Main(string[] args)
    {
        Base C = new Derived();
        C.Method(); //output:"I am Base Class"
    }
}

这样的行为可能会令人困惑,但是如果我们在“Base”中使用“virtual”,在“”中使用“override” >Derived”(我的意思是多态用法)输出是:“I am Derived Class”。 这个输出是我认为我们大多数人所期望的。

换句话说,我相信在层次结构中,大多数开发人员期望在派生类中重写方法而不是想要隐藏基类实现的新方法。

我不明白为什么在c#语言中有这么一个没有优势的坏东西?至少我想知道隐藏在 c# 中的方法的最佳用法是什么?

感谢您的帮助

【问题讨论】:

  • “无法实现预期行为” - 这取决于开发人员的预期。如果他期望非虚拟方法以虚拟方式运行,那是一个有缺陷的期望。
  • 这里有一个例子:如果你有一个 Animals 的集合,并且遍历集合以在每个 Animal 上调用 Speak(),你不希望 Cows 说“Moo”而 Dogs 说“汪”?
  • @mbeckish 这是您确实需要虚拟方法的人为情况。一个反例并不能否定整个功能。
  • 我不确定您是否正确使用了“方法隐藏”一词。您的代码示例是方法隐藏的示例。如果该方法是虚拟的,那么它将是方法覆盖。你说哪个不是好东西?

标签: c# methods method-hiding


【解决方案1】:

如果您需要在派生类中使用新方法,您可以在派生类中使用新名称定义新方法

并非总是如此。考虑派生一个在其他库中公开的类的情况,您无法控制该类。你向你的类添加一些方法。

后来,您所依赖的库的开发人员添加了一些增强功能,并使用与您添加到派生类中的方法之一相同的名称。在这种情况下隐藏只是保留现有功能。如果您更改方法名称,则必须更新整个代码库,并且会破坏与使用您的库的任何人的兼容性。相反,您可以隐藏现有方法并同时保持与您的依赖项以及您所依赖的库的兼容性。

就个人而言,我使用方法隐藏最多的情况是在多个类上实现克隆操作时;如果没有此功能,我无法更改返回类型以匹配该类:

class A
{
    public A Clone()
    {
        return CloneImpl();
    }

    protected virtual A CloneImpl()
    {
        return MemberwiseClone();
    }
}

class B : A
{
    new public B Clone()
    {
        return (B)CloneImpl();
    }
}

受保护的虚方法意味着无论您调用哪个Clone(),您仍然可以返回正确类型的对象。但是,您获得的引用类型将取决于您用来调用Clone() 的引用类型。这允许:

B b = new B();
B b2 = b.Clone(); // Did not have to cast, thanks to the hiding method.

A a = b;
A a2 = a.Clone(); // Still returns a B, only typed as an A.

【讨论】:

  • 啊,脆弱的基类示例。这就是为什么最好尽可能使用组合而不是继承的原因之一。
  • @Servy 我同意。我希望 C# 在这方面提供更多;实现两个接口然后将它们委托给成员对象是很痛苦的。编写样板代码并不是一个有趣的练习。 (特别是指您希望将组合对象公开为“一个”的情况——我现在忘记了该模式的名称。)
  • 不幸的是,问题已经结束,但出于好奇,即使在这种情况下,如果第一个开发人员在基类中使用“虚拟”,您可以“覆盖”派生类中的方法。我的意思是即使在这种情况下“覆盖”更好,如果在 C# 中方法的定义默认是“虚拟”,则不需要隐藏方法。我对吗?
  • @siamak 否。如果默认情况下方法是虚拟/覆盖(想想 Java),那么在父类中添加新方法可能会导致派生类中的方法突然覆盖它,这可能是不受欢迎的行为,并可能产生不良后果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多