0

In C# or Java, how can I make a class that can only be instantiate with the Interfaces it implemented on?

Sorry if this question is asked before.

Edit: Sorry for confusing you, and this question is just asked out of curious:

For example I have:

interface iA
{
  int addNum();
}

interface iB
{
  int minusNum();
}

class A implements iA, iB
{
  private int A;
  public int addNum()
  {
    A += 10;
    return A;
  }

  public int minusNum()
  {
    A -= 10;
    return A;
  }
}

class TestIface
{
  public static void main(String args[]) {
    A testA = new A();
    iA testiA = new A();
    iB testiB = new A();

    testA.minusNum(); // No error, it has access to both methods
    testA.addNum();

    testiA.minusNum();//ERROR
    testiA.addNum();

    testiB.minusNum();
    testiB.addNum();//ERROR
  }
}

I wonder if there is a way to prevent dev from just make testA and access both methods.

Tr1et
  • 873
  • 11
  • 25
  • No such thing exist. – Sriram Sakthivel Sep 13 '14 at 16:05
  • possible duplicate of [How are Java interfaces actually used?](http://stackoverflow.com/questions/504904/how-are-java-interfaces-actually-used) – Ken de Guzman Sep 13 '14 at 16:06
  • 2
    What do you gain by doing this? – Sotirios Delimanolis Sep 13 '14 at 16:06
  • Hide the constructor, and the provide a creator function like `CreateA`. – jww Sep 13 '14 at 16:08
  • Can you explain what exactly do you mean by "instantiate with the Interfaces it implemented on"? It is confusing since (1) your interface `iA` doesn't have any method which returns any instance of `iA` (2) in your title you asked about accessing your class, which is not exactly same as instantiating it. – Pshemo Sep 13 '14 at 16:10
  • 1
    you could *potentially* make the implementation(s) a nested class of a factory that only returns interfaces. The question is though, why? – Dan Sep 13 '14 at 16:13
  • 1
    1. Make a factory and instantiate your class only using that factory (Provider Pattern), 2. Use Unity Container that instantiate classes. The 3rd recommendation is explaining why and then you could get better answers – ilansch Sep 13 '14 at 16:19
  • I'm sorry. I'm still new and just curious that how it is so easy to pass the Interface, like a object with multiple Interface for different kinds of user, then one can easy use what they should not use. – Tr1et Sep 13 '14 at 17:21
  • @DanPantry: An advantage of having the implementing class private is that it ensures that any outside code which is capable of using the class will be able to accept the interface type. Personally, I dislike the fact that constructors in Java are "special" when invoked by a "new" expression outside their own class. Most of the time when code needs a new object that is usable as a `Widget`, it shouldn't care whether it receives an instance of type `Widget` versus some derived class; nonetheless, `someVariable = new Widget();` forces `Widget` to supply an instance of its exact type. – supercat Sep 13 '14 at 17:59
  • @supercat returning an instance of the interface is great and I agree with it. I don't know why you would want to make an implementer private though! There should only be one point of contact with the *real* class in this case, which would be when the class is created. Presumably after this point outside of that scope the class is referred to by it's interface. – Dan Sep 13 '14 at 18:14
  • @DanPantry: Assume class is called cFoo, the interface iFoo, and the factory iFoo.create(). Making cFoo public makes it possible for outside code to rely upon the fact that iFoo.create() returns a cFoo; even if such reliance would offer no benefit, it creates the possibility that modifying `iFoo.create()` so it can return something that isn't a cFoo() would break outside code. Can you think of any positive benefit outside code could receive from being able to use references of type cFoo? – supercat Sep 13 '14 at 18:26
  • unit testing is pretty important.. – Dan Sep 13 '14 at 18:47

3 Answers3

3

How about making the constructor private?

class A implements iA
{
  public int returnNum()
  {
    return 10;
  }
  private A(){}

  public static iA getInstance(){
    return new A();
  }

}
ajay.patel
  • 1,957
  • 12
  • 15
  • 1
    Code as posted is useless(unless you make getInstance static) – Sriram Sakthivel Sep 13 '14 at 16:08
  • This does not prevent someone from creating another concrete implementation of the interface that uses a public constructor, thus not filling the OP's (impossible) requirements. – Hovercraft Full Of Eels Sep 13 '14 at 16:09
  • @HovercraftFullOfEels Can you explain for me about "creating another concrete implementation of the interface that uses a public constructor", I dont understand? – Tr1et Sep 13 '14 at 17:49
  • @Tr1et He's pointing out that there's no way to stop someone from implementing `iA` in a new class with a public constructor. – Preston Guillot Sep 13 '14 at 17:56
1

You can make the constructor private and define a static Create method that creates new instances.

  public interface ITest
  {
  }
  public class A : ITest
  {
      private A()
      {
      }
      public static ITest Create()
      {
          return new A();
      }
  }

Then the only way to create an instance of your class (besides reflection, but that's another story!) is to call the Create method like this:

ITest test = A.Create();
brz
  • 5,926
  • 1
  • 18
  • 18
  • So, why not: A test = A.Create(), test will still gain access to most methods right? – Tr1et Sep 13 '14 at 17:26
  • You can't do that as it give you a compile error. The only way to use A.Create() result as an instance of A is through explicit cast. – brz Sep 13 '14 at 17:28
  • @Tr1et Because callers only know that `A.Create` returns an instance of `ITest`. That the implementation of `A.Create` actually returns an instance of `A` is an implementation detail with the method signature shown. – Preston Guillot Sep 13 '14 at 17:49
0

You cannot instantiate something via an interface. You can only declare it as an interface. If your goal is to make addNum only accessible via iA and minusNum only accessible via iB, you can try explicit interface implementation (although it has its own drawbacks):

class A : iA, iB
{
    private int A;

    int iA.addNum()
    {
        A += 10;
        return A;
    }

    int iB.minusNum()
    {
        A -= 10;
        return A;
    }
}

This will at least give you the compile time effect you are looking for:

class TestIface
{
    public static void main(String args[]) {

        A testA = new A();
        testA.minusNum(); // does not compile
        testA.addNum();   // does not compile

        iA testiA = new A ();
        testiA.minusNum();//does not compile
        testiA.addNum();

        iB testiB = new A ();
        testiB.minusNum();
        testiB.addNum();//does not compile
    }
}

However, this does not mean addNum is only accessible via a variable which is declared as iA. To illustrate, you can do:

A testObj = new A ();
(testObj as iA).addNum (); // this will compile

You can even do:

iB testObj = new A ();
(testObj as iA).addNum (); // this will also compile, and execute fine

If you want to further prevent the explicit casting from and to the concrete class, you need have to take the advice others have offered: make your concrete class a nested private class and introduce a factory to produce the instance:

class Factory
{
    private class A : iA, iB
    {
        int iA.addNum () {...}
        int iB.minusNum () {...}
    }

    public iA GetInstanceOfiA () 
    {
        return new A ();
    }

    public iB GetInstanceOfiB () 
    {
        return new A ();
    }
}

This still does not prevent the casting from iA to iB, which I guess you have to create two separate concrete classes to cater.

Xinchao
  • 2,929
  • 1
  • 24
  • 39
  • Thank you, I am suprised that it is able to write method like: iA.addNum(), is it Java only or is available to C# too? – Tr1et Sep 16 '14 at 06:33
  • It is C# specific. Search for "explicit interface implementation" on either StackOverflow or Goggle will give a lot of examples – Xinchao Sep 16 '14 at 10:53