有没有一种方法可以在子类中部分隐藏方法?

6

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

有人问我,在C#中是否有一种方法可以部分隐藏继承子类中的方法?假设基类A公开了4个方法。B类实现了A类,但只能访问前两个方法,而C类实现了A类,但只能访问后两个方法。

我知道我们可以这样做:

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#中,我们是否有办法实现类似以下的功能...
6个回答

3
我通过创建一个主基类和两个子基类来实现它。
// 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,是的,我们可以这样做...但问题在于当继承基类本身时,方法必须被隐藏... - RameshVel

0

不要使用继承。它会直接将基类的公共或受保护的成员在派生类中可用,所以这并不是你想要的。

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

class firstChild : IFirstOne 
{
    private baseClass _owned = new baseClass();

    public void method1() { _owned.method1(); }
    // etc.
}

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


0

将基类注入为 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(); }
}

注入可以避免违反接口隔离原则。纯继承意味着你的FirstChild依赖于它不使用的接口。如果你想在Base中仅保留IFirst功能,而忽略其余部分,则不能纯粹地从Base继承。


0

也许面试官指的是方法隐藏

这是您声明一个与基类中的方法具有相同签名的方法的地方 - 但您不使用override关键字(因为您不需要或无法使用,例如当基类中的方法是非虚拟的时)。

方法隐藏与覆盖相反,允许您定义完全不同的方法 - 只能通过对派生类的引用调用该方法。如果通过对基类的引用调用,则会调用基类上的原始方法。


0

有两种方法可以隐藏从基类继承的方法:

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

敬礼。


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