2010-07-05 63 views
2

我有以下代码。我需要隐藏界面的一个功能。部分受保护的接口,但没有抽象类

interface IOne 
{ 
    int FunctionOne(); 
} 

interface ITwo 
{ 
    double FunctionTwo(); 
} 

interface IInterfaceToImplement : IOne, ITwo 
{ 
    void AFunctionToImplement(); 
} 

public abstract MyBaseClass : TheVeryHeavyBaseClass<T, IInterfaceToImplement>, IInterfaceToImplement 
{ 
    public abstract void AFunctionToImplement(); // How to force this one to be protected? 

    public virtual int FunctionOne() { return 0; } 

    public virtual double FunctionTwo() { return 0.0; } 
} 

public MyConcreteClass : MyBaseClass 
{ 
    public override void AFunctionToImplement(); // How to force this one to be protected? 
} 

正如你所看到的我有基类。我需要隐藏AFunctionToImplement()。我有差劲的课程设计吗?有关如何保护函数不被调用的任何建议?

编辑。在评论中回答Pavel Minaev的问题。

我需要每个具体类实现IInterfaceToImplement中的函数列表。另外我需要每个具体类都能够存储IInterfaceToImplement类型的类。 这是树形数据存储。存储的每个“分支”都必须执行与其他分支相同的操作。但除了“根”和其他“分枝”之外,其他人都不得不称之为这些操作。

EDIT2我的解决方案。

谢谢马修雅培和帕维尔米娜夫。我终于意识到我的问题 - 这是大脑。 :)

不,我在开玩笑。 :)问题是 - 我想到了根分支类和同一分支。现在我明白了 - 根不应该执行IInterfaceToImplement。查看解决方案:

public class MyRootClass : IOne, ITwo 
{ 
    private IInterfaceToImplement internalData = new MyConcreteClass(); 

    public int FunctionOne() { return this.internalData.FunctionOne(); } 

    public double FunctionTwo() { return this.internalData.FunctionTwo(); } 
} 
+0

你究竟想要达到什么目的?接口是定义的公共契约,但将接口定义保密是没有意义的。有时候让特定的实现是半私有的是有道理的,但是因为人们总是可以获得对同一个对象的接口类型引用,并通过它调用接口方法,所以接口实现永远也不可能真正是私有的。所以...你想要做什么? – 2010-07-05 08:04:17

回答

1
public class MyRootClass : IOne, ITwo 
{ 
    private IInterfaceToImplement internalData = new MyConcreteClass(); 

    public int FunctionOne() { return this.internalData.FunctionOne(); } 

    public double FunctionTwo() { return this.internalData.FunctionTwo(); } 
} 
1

接口只能为公共成员定义。如果你想要一个方法只被定义为受保护的,那么不要为它创建一个接口,而只是将它创建为抽象基类的受保护抽象成员。即使你使用显式接口,如果实例是相关接口类型的情况下,它仍然可以公开访问。

public abstract MyBaseClass<T> : TheVeryHeavyBaseClass<T> 
{ 
    // remove the interface the defined this 
    protected abstract void AFunctionToImplement(); 

    // other code 
} 
+0

我知道这一切。您会在哪里建议申报受保护的会员(请参阅问题中的代码)? – 2010-07-05 07:49:58

+0

不幸的是我不能改变'TheVeryHeavyBaseClass'。我不受我控制。 'TheVeryHeavyBaseClass'有两个通用参数,第二个必须是'IInterfaceToImplement'和MyBaseClass。谢谢你的尝试! – 2010-07-05 08:30:42

+0

看起来像你自己的选择将明确暗示界面。然后创建它调用的第二个方法。 – 2010-07-05 17:31:40

2

我会建议使用显式接口实现:

void IInterfaceToImplement.AFunctionToImplement(); 

...但是,这不会让你揭露和实现在子类中的方法,仍然有它隐藏起来。在这种情况下,您可能想重新考虑您的班级设计。

你最好的选择,它像以下:

public interface IMyInterface 
{ 
    void DoWork(); 
} 

public abstract class MyInterfaceBase : IMyInterface 
{ 
    /// <summary> 
    /// Forced implementation. 
    /// </summary> 
    protected abstract void DoWork(); 

    /// <summary> 
    /// Explicit implementation. 
    /// </summary> 
    void IMyInterface.DoWork() 
    { 
     // Explicit work here. 

     this.DoWork(); 
    } 
} 

这仍然留下,而不是MyInterfaceBase参考其公开曝光,如果该方法是从IMyInterface的参考又称为DoWork的的问题。你根本无法解决这个问题。如果我做了以下内容:

MyInterface first = new MyInterface(); // Let's assume I have implemented MyInterface : MyInterfaceBase 
first.DoWork(); // Compile error, can't access method here. 

鉴于:

IMyInterface second = new MyInterface(); 
second.DoWork(); // No problem. 

你能看到的问题?

+0

欢迎任何设计方案!随时建议对我的课程设计进行任何更改。 :) – 2010-07-05 07:52:08

+1

问题是,为什么你需要隐藏这种方法? – 2010-07-05 07:53:26

+0

实际上,子类可以重新实现显式接口实现。他们不能做的是通过'base'调用基类的实现(因为它实际上是私有的)。但是我们总是可以声明'protected virtual AFunctionToImplement',以此来界定显式接口,并且将后者委托给前者。这样,子类可以覆盖那个_and_使用'base'。 – 2010-07-05 08:02:44

1

每当你编写一个接口时,你都隐式地声明了实现它的任何类的公共视图,所以试图隐藏它的方法是没有意义的。你可以从界面中取出AFunctionImplementation,并将它留在MyBase类中。任何MyBase类的实现仍然可以访问它。

在这种情况下您还可以使MyBase类直接实现IOne和ITwo。

将一个名为'Implementation'的函数作为其名称的一部分将是一个很好的提示,可以避免将其放入界面中,因为通常将界面用作隔离使用情况与实现细节的手段。

+0

我认为你的建议。问题是'TheVeryHeavyBaseClass'的第二个通用参数,MyBaseClass必须实现相同的单一接口(但不是两个)。 – 2010-07-05 08:33:40

1

也许你可以使该方法在虚拟抽象类,然后抛出一个异常

/// <summary> 
    /// Available only in derived classes 
    /// </summary> 
    public virtual void AFunctionToImplement2() 
    { 
     throw new ProtectedMethodException("Please do not call this method in the base class:) "); 
    } 

我不知道这是一个愚蠢的解决方案,但至少你不允许用户即使它是公开的,也使用该方法。

+0

这是类的实现方式。试图避免这一点。 – 2010-07-05 08:50:03