tags:

views:

301

answers:

7

I need to write a function that accepts an object , but I want to enforce in the function call (not after the function is called) that the object is an interface.

Meaning , I want to make sure this is an Interface at compile time , not on run time.

What do I mean?

interface ISomething {...} 
class A implements ISomething { ... }
ISomething something = new A(); 
MyClass.register(something);

In this example , the passed object is an interface , and I want that the MyClass.register function to enforce the this requirment in it's declaration.

I don't know which interface I'm going to get , and there is no use defining another interface to be implemented by all other implementation , because I need the real interface.

+5  A: 

You can't instantiate an interface so you would never be able to create one to send in. You can specify an interface in the parameters for the function and only objects which implement that interface can be passed in. But there is no way to require an interface be what is passed in because you can't create them.

I think you need to rethink what you're trying to accomplish.

John Munsch
They can not be created , but the passed reference to an object can be of type of an interface. see above
yossale
+10  A: 

To accept only objects that implement an interface as argument, use the interface as type, i.e.:

void acceptMaps(Map argument) {
}

can be called with objects implementing the Map interface, like HashMap but not with Strings for instance as they do not implement Map.

Is this what you meant with your question?

Edit in this example, objects implementing SortedMap which extends Map are accepted too, so in your case you could create a BaseInterface and extend that in the interfaces (like AcceptedInterface extends BaseInterface) you want to be accepted by your .register(BaseInterface arg) method.

rsp
.. not what yossale asked for. Don't think Java to answer his question. He does not want to declare the interface in the method signature but enforce, that the method call is only done with a variable that is declared on the (or a) Interface. Please have a look at my answer, that clarifies my comment.
Andreas_D
A: 

You can ask the class of the object you get interfaces it implements during runtime. If you can't already give the compiler the types of the interfaces you expect it has no way to predict what is going to be passed into your method so you will have to use runtime reflection.

Daff
err .. arg is never an interface. I thought of this as well, but arg is nothing but an 'A' instance that implements ISomething (as of yossales example)
Andreas_D
I didn't want to use reflection , but apparently there's no other choice. Thanks!
yossale
This method will always throw an exception: arg.getClass() will never be an interface.
Kathy Van Stone
Yes you do... if the compiler doesn't have any idea what will be coming along the way is no way around checking it at runtime. @Andreas_D: Thanks, you're right. You should get a list of interfaces implemented by this Object instance.
Daff
after the edit - correct, but now it's not a solution for the problem anymore ;)
Andreas_D
Ah damn you're right again. Ok no code samples just the fact that it is not possible to do what was being asked for during compile time.
Daff
A: 

There's no way to check at runtime, if the 'object is an interface' because an object can never ever be 'an interface', it only be an instance of a class that implements an interface.

And it's not possible to restrict a method signature to interface usage, say you'll allow type 'Animal' but not type 'Dog' which implements animal behavior. (I guess that's what you were looking for)

Taking your example - you want a compiler error for this implementation:

interface ISomething {...} 
class A implements ISomething { ... }
ISomething something = new A(); 
MyClass.register(something);

A unwanted = (A) something;
MyClass.register(unwanted); // <- compilation error here

But practically spoken - I see no immediate reason. If you want to enforce programmers to use interfaces - user code inspection or quality check tools. If you want to restrict instantiation of an implementation, protect the constructor and use a factory to produce instances.

Andreas_D
Daff has done it :P
01
.. no, his solution is wrong. It will always throw an IAE, because the class of the passed object is never an interface. :P
Andreas_D
"If you want to enforce programmers to use interfaces - user code inspection or quality check tools." No no! That's what compilers are for! The compiler can easily validate that the passed-in object implements the desired interface. Why not use that feature?
Jay
I still believe, that's not what yossale was looking for. I think, he wants to enforce, that the variable, that is used in MyClass.register(Object o) is of an Interface type, not of a Class type. At compile time. The idea is not even bad, but that's not possible with the java compiler.
Andreas_D
.. was the downvote honest or just a revenge for my other comments? Explanation could be helpful.
Andreas_D
+4  A: 

You're making a distinction between the type of the object (in this case A) and the type of the reference to the object (in this case ISomething).

Sounds like you want to permit this code:

ISomething something = new A(); 
MyClass.register(something);

but forbid this code:

A something = new A(); 
MyClass.register(something);

I don't think you can achieve this with Java.

monorailkitty
+1  A: 

Let me see if I understand.

Do you want to check at compile time that the argument passed to a function is some interface? Any interface?

If that's the question, the answer is you can't.

I don't know which interface I'm going to get [...] I need the real interface.

You can't actually validate if you don't know which type to expect.

In Java you need to know the type to validate the parameter, the argument must be of the same type or a descendant, Java doesn't make distinctions on this regard at compile time, you can make it at runtime as Daff aswered.

OscarRyz
Well, I presume he means that he doesn't know which specific class he's going to get, just that it will be a class that implements the interface. Give the poor guy a break: He's trying to explain his problem, we all have trouble explaining it clearly now and then.
Jay
@Jay: mmmhh who knows, the question is not that clear. Well if he knows the interface it will be very easy `void method( SomeInterface f ){...}` if as I understood he just want to validate *any* interface, there is not way. Let's wait for comments yosalle
OscarRyz
A: 

"The object is an interface" doesn't make sense. It seems like you want to enforce that the pointer passed into the function was declared with an interface type like

Interface_t x = new Class_which_implements_interface_t();

as opposed to

Class_which_implements_interface_t y = new Class_which_imlements_interface_t();

The only problem is that if you make a function like this:

void some_func(Interface_t z) {...}

And you call it with some_func(x); or some_func(y); the function is passing the reference by value, which means that inside of some_func, z is a copy of x or y which has been casted to an Interface_t pointer. There is no way to get information about what type the original pointer had. As long as it is able to be casted to an Interface_t it will compile and run.

Graphics Noob