简体   繁体   English

部分受保护的接口,但没有抽象类

[英]Partially protected interface but without abstract class

I have following code. 我有以下代码。 And I need to hide one function of the interface. 而且我需要隐藏界面的一项功能。

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?
}

As you can see I have base class. 如您所见,我有基类。 And I need the AFunctionToImplement() to be hidden. 而且我需要隐藏AFunctionToImplement() Do I have poor classes design? 我的班级设计不好吗? Any suggestions on how to protected the function from being called? 关于如何保护函数免受调用的任何建议?

EDIT. 编辑。 Answer to Pavel Minaev question in the comments. 在评论中回答Pavel Minaev问题。

I need every concrete class implement the list of functions from IInterfaceToImplement. 我需要每个具体的类都实现IInterfaceToImplement的功能列表。 Also I need every concrete class to be able to store classes of IInterfaceToImplement type. 另外,我需要每个具体的类都能够存储IInterfaceToImplement类型的类。 This is tree-like data storage. 这是树状的数据存储。 Every 'branch' of the storage have to perform same operations as any other branch. 存储的每个“分支”必须执行与任何其他分支相同的操作。 But nobody else except the 'root' and other 'braches' must call these operations. 但是除了“根”和其他“分支”之外,没有其他人必须调用这些操作。

EDIT2 My solution. EDIT2我的解决方案。

Thanks Matthew Abbott and Pavel Minaev. 感谢Matthew Abbott和Pavel Minaev。 I finally realized my problem - it is brain. 我终于意识到我的问题-这是大脑。 :) :)

No, I'm joking. 不,我在开玩笑。 :) The problem is - I thought of root and branch classes as of the same branch. :)问题是-我认为根类和分支类与同一分支相同。 Now I understand - the root should not implement IInterfaceToImplement . 现在我明白了-根目录不应该实现IInterfaceToImplement See the solution: 查看解决方案:

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

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

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

I would suggest using an explicit interface implementation: 我建议使用显式接口实现:

void IInterfaceToImplement.AFunctionToImplement();

...but that wouldn't allow you to expose and implement the method in subclasses and still have it hidden. ...但是这不允许您在子类中公开和实现该方法,并且仍然将其隐藏。 You may want to rethink your class design in this case. 在这种情况下,您可能需要重新考虑您的班级设计。

Your best bet, it something like the following: 最好的选择是,它类似于以下内容:

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();
    }
}

This still leaves the issues of having the DoWork publicly exposed if the method is called from an IMyInterface reference, instead of a MyInterfaceBase reference. 如果从IMyInterface引用而不是MyInterfaceBase引用调用该方法,则仍然存在公开公开DoWork的问题。 You simply can't get round this. 您根本无法解决这个问题。 If I did the following: 如果我执行以下操作:

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

Whereas: 鉴于:

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

Can you see the issue? 你看到这个问题了吗?

Interfaces can only be defined for public members. 只能为公共成员定义接口。 If you want a method to only be defined as protected then don't make an interface for it and just create it as a protected abstract member of the abstract base class. 如果要只将方法定义为受保护的方法,则不要为其创建接口,而只需将其创建为抽象基类的受保护抽象成员即可。 Even if you were to use the explicit interface it would still be publicly accessible if the instance is case to the related interface type. 即使您使用显式接口,如果该实例属于相关接口类型,它仍然可以公开访问。

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

    // other code
} 

Whenever you write an interface you're implicitly declaring a public view of any class that implements it, so it wouldn't make sense at all to try and hide its methods. 每当您编写接口时,您都在隐式声明一个实现该接口的任何类的公共视图,因此尝试隐藏其方法根本没有任何意义。 You can take AFunctionImplementation out of the interface and leave it live in MyBase class. 您可以将AFunctionImplementation移出接口,并将其保留在MyBase类中。 Any implementation of MyBase class would still have access to it. MyBase类的任何实现仍然可以访问它。

In this case you can also make MyBase class implement IOne and ITwo directly. 在这种情况下,您还可以使MyBase类直接实现IOne和ITwo。

Having a function with the word 'Implementation' as part of its name would be a good hint to avoid putting it in an interface, as interfaces are often used as a means to isolate usage from implementation details. 在名称中使用“ Implementation”一词作为功能的一部分将是避免将其放在接口中的一个很好的提示,因为接口通常被用作将用法与实现细节隔离开的手段。

Maybe you could make the method virtual in the abstract class and then throw an exception 也许您可以在抽象类中将方法虚拟化,然后引发异常

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

I don't know if this is a silly solution, but at least you don't allow the users to use the method even if it's public. 我不知道这是否是一个愚蠢的解决方案,但是至少您不允许用户使用该方法,即使该方法是公开的也是如此。

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM