Lesson 4: Interfaces
Introduction
Interface and abstract class types pose a problem because we might need to instantiate a proxy object for
which we have nothing but a proxy interface type. To illustrate that problem, let's look at a generic Java
object factory that can return objects of a totally unknown Java type. All we know is that the returned object implements
the interface MyIfc
.
Given a Java type like
public class MyFactory { public MyIfc create( Mapinputs ) { ... }; }
The .NET proxy type for the MyFactory
type will look something like this (much code omitted):
public class MyFactory : global::Java.Lang.Object { public global::MyIfc Create( global::Java.Util.Map inputs ) { ... }; }
You see that the .NET type is declared to return a MyIfc
instance. But we can't know the exact Java type
that is going to be returned and therefore we (probably) don't have the exact .NET proxy type that would match that
unknown Java type. Yet we need a .NET type that can be instantiated and that implements the MyIfc
interface,
otherwise we can't return an object from the Create()
method.
Impl Types to the Rescue
We solve this problem with an additional type that we refer to as an "Impl
type." Every proxy type for
an abstract Java type, interfaces included, has a nested type that has the outer type's name plus "Impl"
. In
our example case, the nested type would be called MyIfcImpl
. That type satisfies all contracts of a proxy object
while implementing or extending its outer type.
Please note that you do not have to and in fact should never declare a variable of an Impl
type. Consider
the following snippet that uses our factory class:
// do NOT do this MyIfc.MyIfcImpl impl = (MyIfc.MyIfcImpl)factory.Create( null );
This might work for you in most cases but there's no need to do it and it might actually be harmful. What if you have a
proxy type for one of the Java types that are being returned
by the factory method? In that case the JuggerNET runtime will return the proper proxy type and not
an Impl
type and you will get a runtime error. Use the object via its declared interface and treat the
Impl
type as the implementation detail that it is.
If you are only ever going to use the proxy object via its declared interface API you have absolutely no unexpected
behavior. An issue can arise though when you use your expert knowledge about the returned object to cast it to a different
interface that the returned Java type also implements. That won't work on the .NET proxy object because it only implements
the one interface that was the declared return type. When you face that situation you will have to use the other
interface Impl
type's From()
method to convert the proxy instance to the other type. This is described at much greater
detail in the casting lesson.