views:

102

answers:

5

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. 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.

I need every concrete class implement the list of functions from IInterfaceToImplement. Also I need every concrete class to be able to store classes of IInterfaceToImplement type. 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.

Thanks Matthew Abbott and 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. 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(); }
}
A: 

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
} 
Matthew Whited
I know all that. Where would you recommend to declare the protected member (see code in the question)?
Vasiliy Borovyak
Unfortunately I can't change `TheVeryHeavyBaseClass`. I's not under my control. And `TheVeryHeavyBaseClass` have two generic parameters, second one must be `IInterfaceToImplement` as well as MyBaseClass. Thanks for the try!
Vasiliy Borovyak
Looks like your ownly option is going to be explictly implmenting the interface. And then Creating a second method that it calls.
Matthew Whited
See Matthew Abbott's answer http://stackoverflow.com/questions/3177753/partially-protected-interface-but-without-abstract-class/3177848#3177848
Matthew Whited
+2  A: 

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

Matthew Abbott
I'm welcome to any design proposes! Feel free to suggest any changes to my class design. :)
Vasiliy Borovyak
Question is, why do you need that method to be hidden?
Matthew Abbott
Subclasses can re-implement explicit interface implementations, actually. What they can't do is call the base class implementation via `base` (because it's effectively private). But one can always also declare `protected virtual AFunctionToImplement` _alongside_ the explicit interface implementation, and have the latter delegate to the former. That way, the subclasses can override that _and_ use `base`.
Pavel Minaev
This would force any class that implements the interface to do this 'trick'.
Trap
first.DoWork()this will work if you cast first with your interface. ((IMyInterface) first).DoWork()
IBhadelia
Nice approach! But still methods are possible to call from outside. :(
Vasiliy Borovyak
+1  A: 

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. Any implementation of MyBase class would still have access to it.

In this case you can also make MyBase class implement IOne and ITwo directly.

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.

Trap
I thought your suggestion. The problem is second generic parameter of `TheVeryHeavyBaseClass` and the MyBaseClass must both implement same single interface (but not two).
Vasiliy Borovyak
A: 

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.

Flavius
It's the way classes are implemented at the moment. :) And I'm trying to avoid this.
Vasiliy Borovyak
A: 
public class MyRootClass : IOne, ITwo
{
    private IInterfaceToImplement internalData = new MyConcreteClass();

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

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