Cheetah
Cheetah

Reputation: 14431

How to hide implementation

Lets say I have a class library, where any classes that are internal have access to the following interface:

interface myInterface
{
    string myProperty { get; set; } // notice setter.
}

But if somebody adds this class library to their project they get the following interface:

public interface myInterface
{
    string myProperty { get; }
}

What is the most efficient and accepted way of doing this? Have one interface implement the other?

Upvotes: 6

Views: 2332

Answers (3)

vidstige
vidstige

Reputation: 13085

You can have the internal interface extend the public interface, like so:

public interface MyInternalInterface: MyPublicInterface
{
    string MyProperty { set; }
}

public interface MyPublicInterface
{
    string MyProperty { get; }
}

internal class A: MyInternalInterface
{
    public string MyProperty { get; set; }
}

public class Foo
{
    private A _a = new A();
    internal MyInternalInterface GetInternalA() { return _a; }
    public MyPublicInterface GetA() { return _a; }

}

This way you don't need any casts or anything.

Upvotes: 1

Andras Zoltan
Andras Zoltan

Reputation: 42363

I thought that @adrianbanks' answer might be an improvement on mine, however I don't think it really is (despite being nifty) - because you have no guarantee that a public interface instance being passed to you also implements the internal one - which is also true of this solution. There's also the thing that it only works if the implementing type is internal - which is no good if you want to supply public types as standard interface implementations or as bases for a hierarchy.

This is what I use. Given:

interface myInterface
{
  string myProperty { get; set; }
}

public interface myPublicInterface
{
  string myProperty { get; }
}

First you can't make myPublicInterface inherit myInterface because the compiler will moan about inconsistent accessibility. So you can explicitly implement the internal one, using a property backer, and then implement the public one implicitly:

public class MyClass : myInterface, myPublicInterface
{
    private string _myProperty;

    string myInterface.myProperty
    {
        get { return _myProperty; }
        set { _myProperty = value; }
    }

    public string myProperty
    {
        get { return _myProperty; }
    }
}

Note - in some cases, the getter might not be suitable for a private backer, but might be some logic that calculates values from other properties. In which case - to keep it DRY - you can put the logic in the public getter, and leech that for the explicit getter:

string myInterface.myProperty
{
  get { return MyProperty; }
  set { /*whatever logic you need to set the value*/ }
}

public string myProperty
{
  get { /*whatever complex logic is used to get the value*/ }
}

You can do it the other way around, but you have to do a horrible-looking inline cast to the internal interface:

string myInterface.myProperty
{
  get { /*whatever complex logic is used to get the value*/ }
  set { /*whatever logic you need to set the value*/ }
}

public string myProperty
{
  get { return ((myInterface)this).myProperty; }
}

Which you should try to steer clear of wherever possible.

Upvotes: 0

adrianbanks
adrianbanks

Reputation: 83004

Make your public interface have just the getter:

public interface myInterface
{
    string myProperty { get; } 
}

And then derive another internal-only interface from it that has a setter:

internal interface myInternalInterface : myInterface
{
    new string myProperty { get; set; }
}

You can them implement the internal interface:

class myImplementation : myInternalInterface
{
    public string myProperty{get; set;}
}

If you need to call the setter, you can cast your instance to the internal inteface and call it on that. This approach is a bit of a design smell though, so use it sparingly.

Upvotes: 2

Related Questions