【问题标题】:Hiding derive class method?隐藏派生类方法?
【发布时间】:2024-01-22 20:38:01
【问题描述】:

我们能否隐藏派生类的公共方法,使其不能在 C# 的 Main() 函数中访问。我们无法更改派生类方法的访问器。

public class A
{
    public void Add()
    {
    }    
}       

public class B : A 
{
    public void Multiply()
    {
    }        
}

在 C# 的 main() 方法中

B b = new B();
b.mulitply(); // should give compile time error... Like method not founded.

我们有什么办法吗?

【问题讨论】:

  • 我可以给你 17% 的答案。
  • @Peterchen,避免调用它。请参阅——对象的 ToString。没有办法摆脱它,它会导致错误。而且错误很糟糕:-)
  • @macias: 关于ToString - 怎么样?你能详细说明一下吗?据我了解:在最坏的情况下,它是您可能需要照顾的基类遗产。令人高兴的是,没有很多 - ToString、GetHashCode、Equals。
  • @Peterchen,我更喜欢真正扎实的语言,它只能以明确的方式工作。隐式操作很糟糕,因为它会让代码滑入,这是我疲倦、半醒等的影响。 ToString 用作到字符串的隐式转换,因此编译器将愉快地编译语义不正确的代码。我一遍又一遍地被这个问题所困扰(隐式转换)。在 C++ 中引入了特殊的 Explicit 类只是为了避免这个问题,而在 C# 中它是语言的核心。 ...
  • ... 最近我输入了 var filename = directory+network.Signature()+".xml";你看到错误了吗? Signature 是一个具有复杂数据的类,这样使用它没有任何意义,但它甚至可以在没有警告的情况下编译。运行程序后我看到了什么?名称为“Signature.xml”的文件。我没有时间处理这些微不足道的错误,而且令人沮丧的是语言还没有真正成熟(根据我们所有的经验)。

标签: c# inheritance language-features


【解决方案1】:

绝对不是。它是公共类的公共方法。如果你不能使用它,它不应该是公开的。

(顺便说一下,我不明白它源自 A 的事实有何相关性。)

【讨论】:

  • 好吧,“A”类可能不是您的产品(即您无法控制它)。
  • @macias:当然,您也不能更改System.Object...据我所知,问题中没有任何真正与继承相关的内容。
  • 不是在示例中,而是在问题中? “隐藏派生类方法?”和“我们能否隐藏派生类的公共方法,以便在 C# 的 Main() 函数中无法访问它”。继承就是派生类。
  • @macias:这个问题只涉及“派生类公共方法”——而不是“基类中的公共虚拟方法,在派生类中被覆盖”。鉴于在示例代码中缺少任何明确的不同的方法,我认为假设 OP 确实在谈论一个被覆盖的方法是一个延伸。
  • 无论如何,我不想(太)挑剔,但由于每个类都派生自对象,因此考虑从对象类中隐藏方法的问题也是有效的。代码只是问题的一个示例
【解决方案2】:

这个请求没有任何意义。 B 类声明了一个方法Multiply。为什么这个方法会被隐藏?对谁隐瞒?

【讨论】:

  • 实现这一点的技巧是 A a = new B(); a.multiply() 给出错误()
  • 从误用中隐藏——例如对于很多类 ToString 没有意义(更糟糕的是,其他一些类可以不可见地使用此方法),但我不能每次都隐藏它我必须跟踪愚蠢的错误。这是真正的痛苦。
  • @macias:多态性呢? ToString(),根据定义,总是“有意义”。输出是否有用是一个单独的问题。
  • @John,不——它总是有效,但它很少有意义。而且在不知不觉中犯错太容易了。最近我决定为 object 的每个方法抛出异常,因为让它被忽视太危险了——我更喜欢当场被咬。
  • @macias:太危险了?这没有任何意义。你重写 Equals 来抛出异常?
【解决方案3】:

为什么不直接将方法设为私有?

public class B: A
{
  private void Multiply()
  {
  }
}

如果你绝对不能改变 B,那么我唯一能想到的就是创建一个完整的适配器类。

public C
{
  private B instance;

  private void Multiply(){}

  public void Add()
  {
    B.Add();
  }
}

这将迫使您“复制” B 中的所有方法,但您想要的方法除外。

如果您绝对需要类为“B”,则必须使用反射器对其进行反向引擎并将公共字段更改为私有或受保护。

【讨论】:

  • 我们不能改变public accessors,有人在采访中问过这个问题? :-D。我也这么说,但他不同意。
  • 因为它不起作用。如果您覆盖它不能是私有的,如果您将其定义为新的,它将被忽略(即将调用继承的版本)。
  • @macias:没有压倒一切的事情发生。查看方法名称:相加和相乘。哎呀,它们都没有被指定为虚拟的。
  • 我唯一想不到的是在 B 之上的一个完整的适配器,然后只使用 C 作为与 B 的接口。
  • @Jon,我错过了这里缺少的虚拟,而且......天啊...... 3 行距离,我看到的只是“数学”:-D
【解决方案4】:

函数公开的意义在于它可以在其他地方访问。

你可以私下继承吗? (没有意义)或将成员声明为私有或受保护,因此派生类不会继承它。

【讨论】:

  • 你不能为对象做这个——你总是从对象继承。
  • 我认为你理解错了。一旦您将类作为私有继承,数据成员和方法将变得不可访问,并且将显示编译时错误。对象只是您不继承对象的类的实例。
  • 误解——类“对象”,而不是类的对象。 “object”类是C#中的基础类,其他所有类型都继承自它。
  • C# 没有私有继承。
最近更新 更多