在.Net层次结构中隐藏方法

3

我有三个类:

  1. BaseClass
  2. 从BaseClass继承的Middleclass
  3. 继承自Middleclass的ClientClass

我想知道如何隐藏BaseClass中的方法,以使其不在ClientClass中显示?

示例:

public class BaseClass
{
    public void BaseMethod1()
    {
    }

    public void BaseMethod2()
    {
    }
}

public class MiddleClass : BaseClass
{
    public void MiddleMethod()
    {
        this.BaseMethod1();
    }
}

public class ClientClass : MiddleClass
{
    public void Test()
    {
        this.MiddleMethod();
        this.BaseMethod1(); // I can't see this method here
    }
}

编辑:我修改了我的示例,我将"this.BaseMethod1();"放在MiddleClasse中。


2
你能解释一下为什么要这样做吗? - svick
不公开,还是完全不显示?您可以使用此答案的修改版本,在ClientClass中将其设为私有,同时在MiddleClass中保持其公开。 - yoozer8
1
看起来您在错误的地方使用了继承。 - sll
2
你试图肆意而残酷地违反Liskov 替换原则。这不是一个好主意。 - TeaDrivenDev
4个回答

4
你需要将该方法定义为私有的。仅供参考,这里有关于访问修饰符更多的信息:
- public:该类型或成员可以被同一程序集中的任何其他代码或引用它的另一个程序集中的代码访问。 - private:该类型或成员只能被同一类或结构中的代码访问。 - protected:该类型或成员只能被同一类或结构中的代码或从该类派生的类中的代码访问。 - internal:该类型或成员可以被同一程序集中的任何代码访问,但不能从另一个程序集中访问。

2
我认为这里的隐含问题是如何使方法对ClientClass不可见,同时保持在MiddleClass中可访问,正如其他人指出的那样,这可能需要重新设计。 - anton.burger
谢谢Claudio!我尝试更改访问修饰符,但不起作用。 - Nandoviski

4

我一直认为,如果你想要从某些派生类中隐藏基类的某些功能,但不是全部派生类,则这是一种代码异味,你的设计需要重新思考。


这将违反Liskov替换原则。 - b_meyer

2
尝试一下这个方法,它会打破直接继承树:
public interface IBaseClass
{
    void BaseMethod1();
    void BaseMethod2();
}

public class BaseClass : IBaseClass
{
    public void BaseMethod1()
    {
    }

    public void BaseMethod2()
    {
    }
}

public class MiddleClass : IBaseClass
{
    BaseClass @base;

    public MiddleClass() { this.@base=new BaseClass(); }

    public void MiddleMethod()
    {
        @base.BaseMethod1();
    }

    void IBaseClass.BaseMethod1()
    {
        //@base.BaseMethod1();
        throw new NotImplementedException();
    }

    public void BaseMethod2()
    {
        @base.BaseMethod2();
    }
}

public class ClientClass : MiddleClass
{
    public void Test()
    {
        this.MiddleMethod();
        // 'ClientClass' does not contain a definition for 'BaseMethod1'
        //this.BaseMethod1(); 
    }
}

很接近了。不过你应该知道你仍然可以执行 ((IBaseClass)this).BaseMethod1() - svick
@svick - 现在不行,我已经编辑了帖子,在这种情况下抛出异常。基本方法仅通过MiddleMethod()可访问。 - John Alexiou
回答问题的信,获得积分,不过我不确定是否应该鼓励这种代码... - anton.burger
1
这就是为什么接口被发明出来的原因。用来解决类似这样的松散继承问题。 - John Alexiou
1
可能的缺点是ClientClass不再是BaseClass。如果有其他BaseClass成员,ClientClass原本希望继承它们,现在除非您使用更多的代码通过MiddleClass使它们可用,否则将无法继承。此外,IBaseClass.BaseMethod1现在必须在某些(无法检测到的)情况下被理解为抛出NotImplementedException,这使得在多态方式下使用此层次结构有点像俄罗斯轮盘游戏:P - anton.burger
1
@shambulator - 我同意,因此开发人员需要在 DocXml 中添加免责声明,说明并非所有 IBaseClass 的方法都必须始终实现。 - John Alexiou

0

在BaseClass中将方法BaseMethod1定义为protected,然后您就可以在MiddleClass中使用函数BaseMethod1。

public class BaseClass
{
    protected void BaseMethod1()
    {
    }

    public void BaseMethod2()
    {
    }
}

public class MiddleClass : BaseClass
{
    public void MiddleMethod()
    {
       base.BaseMethod1();
    }
    // hide method
    private new void BaseMethod1()
    {

    }
}

但是如果他在 MiddleClass 中需要基类功能,使用 new 将会覆盖基类实现。 - User 12345678
如果实现是 base.BaseMethod(),那么他将在 MiddleClass 中拥有它,但不会在 ClientClass 中拥有。 - zimdanen
1
@misak 不是这样的。你试过这段代码吗?根据问题定义的ClientClass仍然可以调用BaseClass版本的BaseMethod1 - anton.burger
你不需要像这样使用 new 关键字吗?例如:private new void BaseMethod1() { } - John Alexiou
1
@ja72 这没有什么区别。使用new只是让隐藏变得明显,并防止编译器警告。 - anton.burger
我理解你的观点。虽然这样做可以形成良好的编码风格,不是吗?! - John Alexiou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接