【问题标题】:Is there a way to hide the methods partially in child classes?有没有办法在子类中部分隐藏方法?
【发布时间】:2010-02-16 13:36:43
【问题描述】:

这个问题看起来很奇怪,但我最近在一次采访中遇到了这个问题。

有人问我,c# 中有没有办法在继承的子类中部分隐藏方法?假设基类A,暴露了4个方法。 B 类实现 A,它只能访问前 2 个方法,C 类实现 A 只能访问后 2 个方法。

我知道我们可以这样做

public interface IFirstOne
{
    void method1();        
    void method2();
}

public interface ISecondOne
{
    void method3();
    void method4();
}

class baseClass : IFirstOne, ISecondOne
{
    #region IFirstOne Members

    public void method1()
    {
        throw new NotImplementedException();
    }

    public void method2()
    {
        throw new NotImplementedException();
    }

    #endregion

    #region ISecondOne Members

    public void method3()
    {
        throw new NotImplementedException();
    }

    public void method4()
    {
        throw new NotImplementedException();
    }

    #endregion
}

class firstChild<T> where T : IFirstOne, new()
{
    public void DoTest() 
    {

        T objt = new T();
        objt.method1();
        objt.method2();
    }
}


class secondChild<T> where T : ISecondOne, new()
{
    public void DoTest() 
    {
        T objt = new T();
        objt.method3();
        objt.method4();
    }
}

但他们想要的是不同的。他们想在从基类继承时隐藏这些类。像这样的

class baseClass : IFirstOne, ISecondOne
{
    #region IFirstOne Members

    baseClass()
    {
    }

    public void method1()
    {
        throw new NotImplementedException();
    }

    public void method2()
    {
        throw new NotImplementedException();
    }

    #endregion

    #region ISecondOne Members

    public void method3()
    {
        throw new NotImplementedException();
    }

    public void method4()
    {
        throw new NotImplementedException();
    }

    #endregion
}

class firstChild : baseClass.IFirstOne //I know this syntax is weird, but something similar in the functionality
{
    public void DoTest() 
    {
        method1();
        method2();

    }
}


class secondChild : baseClass.ISecondOne
{
    public void DoTest() 
    {           
        method3();
        method4();
    }
}

在 c# 中有没有办法我们可以实现这样的目标...

【问题讨论】:

    标签: c# inheritance interface


    【解决方案1】:

    我通过拥有 1 个主基类和 2 个子基来做到这一点。

    // Start with Base class of all methods
    public class MyBase
    {
        protected void Method1()
        {
    
        }
    
        protected void Method2()
        {
    
        }
    
        protected void Method3()
        {
    
        }
    
        protected void Method4()
        {
    
        }
    }
    
    // Create a A base class only exposing the methods that are allowed to the A class
    public class MyBaseA : MyBase
    {
        public new void Method1()
        {
            base.Method1();
        }
    
        public new void Method2()
        {
            base.Method2();
        }
    }
    
    // Create a A base class only exposing the methods that are allowed to the B class
    public class MyBaseB : MyBase
    {
        public new void Method3()
        {
            base.Method3();
        }
    
        public new void Method4()
        {
            base.Method4();
        }
    }
    
    // Create classes A and B
    public class A : MyBaseA {}
    
    public class B : MyBaseB {}
    
    public class MyClass
    {
        void Test()
        {
            A a = new A();
    
            // No access to Method 3 or 4
            a.Method1();
            a.Method2();
    
            B b = new B();
    
            // No Access to 1 or 2
            b.Method3();
            b.Method4();
    
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      虽然您不能完全按照您的意愿行事,但您可以使用显式接口实现来提供帮助,其中接口成员只有在显式转换为该接口时才会暴露...

      【讨论】:

      • @thecoop,是的,我们可以这样做..,但问题是在继承基类本身时必须隐藏方法...
      【解决方案3】:

      也许面试官指的是method hiding

      这是您声明一个与基类中具有相同签名的方法的地方 - 但您不使用 override 关键字(因为您不使用或不能 - 就像在基类是非虚拟的)。

      overriding 相比,方法隐藏允许您定义一种完全不同的方法——该方法只能通过对派生类的引用来调用。如果通过对基类的引用调用,您将调用基类上的原始方法。

      【讨论】:

        【解决方案4】:

        不要使用继承。它使基类的公共或受保护设施直接在派生类中可用,所以它根本不是你想要的。

        相反,让派生类实现相关接口,并(如有必要)将方法转发到底层类的私有实例。也就是说,使用组合(或“聚合”)而不是继承来扩展原始类。

        class firstChild : IFirstOne 
        {
            private baseClass _owned = new baseClass();
        
            public void method1() { _owned.method1(); }
            // etc.
        }
        

        顺便说一下,类名应该以大写字母开头。

        【讨论】:

          【解决方案5】:

          隐藏从基类继承的方法有两种解决方案:

          • 正如thecoop所提到的,您可以显式地实现接口来声明您想要隐藏的方法。
          • 或者您可以简单地在基类中创建这些方法(不从任何接口继承)并将它们标记为私有。

          问候。

          【讨论】:

            【解决方案6】:

            将基类作为IFirst 注入怎么样?

            interface IFirst {
                void method1();
                void method2();
            }
            
            interface ISecond {
                void method3();
                void method4();
            }
            
            abstract class Base : IFirst, ISecond {
                public abstract void method1();
                public abstract void method2();
                public abstract void method3();
                public abstract void method4();
            }
            
            class FirstChild : IFirst {
                private readonly IFirst _first;
                public FirstChild(IFirst first) {
                    _first = first;
                }
                public void method1() { _first.method1(); }
                public void method2() { _first.method2(); }
            }
            

            注入可防止您违反Interface Segregation Principle。纯继承意味着您的 FirstChild 依赖于它不使用的接口。如果您只想保留Base 中的IFirst 功能,而忽略其余部分,那么您不能纯粹从Base 继承。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-05-29
              • 2021-09-02
              • 1970-01-01
              • 1970-01-01
              • 2016-01-18
              • 1970-01-01
              • 2020-11-04
              相关资源
              最近更新 更多