Interface
in Java
(Abstract
Class)
interface A { public int m(); } class A1 implements A { public int m() { return 1; }; } class A2 implements A { public int m() { return 2; }; } class M { public void f( A [] x ) { for ( int i = 0; i < x.length;
i++ ) System.out.println( x[i].m()
); } } import
java.io.IOException; public class intTest { public static void main(String args[])
{ A [] a = new A[3]; M mm = new M(); a[0] = new A1(); a[1] = new A2(); a[2] = new A1(); mm.f(a); // 1 2
1 } } interface B extends A { public int n(); } class A3 implements A { public int m() { return 3; } } class B1 extends A1
implements B { public int n() { return -1; }; } class B2 extends A2
implements B { public int n() { return -2; }; } class B3 extends A3
implements B { public int n() { return -3; }; } class N extends M { public void g( B [] x ) { for ( int i = 0; i < x.length;
i++ ) System.out.println( x[i].n()
); } } import
java.io.IOException; public class intTest { public static void main(String args[])
{ B [] b = new B[3]; N nn = new N(); b[0] = new B3(); b[1] = new B2(); b[2] = new B1(); nn.f(b); // 3 2
1 nn.g(b); // -3 -2 -1 } }
/*
Test.java Hongyin
Quan
A simple test program testing the casting
of interface type.
The conclusion is that everything depends
on the dynamic type
of the variable, as long as the dynamic
type allows the casting
you can do whatever casting you like.
*/
interface
I { void m(); }
interface
J { void n(); }
interface
K extends I { void p(); }
class
A implements I, J {
public void m() { System.out.println("This
is m() in A"); }
public void n() {
System.out.println("This is n() in A"); } }
class
B implements I, J {
public void m() {
System.out.println("This is m() in B"); }
public void n() {
System.out.println("This is n() in B"); } }
class
C implements K {
public void m() {
System.out.println("This is m() in C"); }
public void p() {
System.out.println("This is p() in C"); } }
class
D extends A implements K {
public void p() { System.out.println("This is p() in
D"); } }
public
class Test {
public static void main(String [] args) {
I i = new A();
I ii = new B();
J j = new B();
J jj = new A();
// The following accesses are legal
i.m();
ii.m();
j.n();
jj.n();
// The following two lines will get
compile errors since n()
// is not defined in I and m() is not
defined in J.
// i.n();
// ii.n();
// j.m();
// jj.m();
// Now, we will do casting so that i can
access n() and j can access m()
// The following casting are fine
A a = (A) i;
B b = (B) j;
// With the above casting, we can do the
two method invokcations
// that we can not do above.
a.n();
b.m();
// Even more suprising, though I and J
seem have no relationship at all,
// we can cast j from type J to type I and
i from type I to type J !!!!
// The trick here is that A and B are
acting a bridge between these
// two interfaces through Java's dynamic
object type.
I c = (I) j;
J d = (J) i;
// No surprise again here, we can do the
two invocations we can not do above.
c.m();
d.n();
// Interface extension
K k = new C();
K kk = new D();
k.m();
kk.m();
k.p();
kk.p();
// kk.n();
n() not found in K } }
/*
Outputs
This
is m() in A
This
is m() in B
This
is n() in B
This
is n() in A
This
is n() in A
This
is m() in B
This
is m() in B
This
is n() in A
This
is m() in C
This
is m() in A
This
is p() in C
This
is p() in D
*/

Multiple Inheritance
through Interface

Problem: DrawableCircle should be able to inherit both
draw() from DrawableShape (abstract
class), and
area(){
} from Circle
but Java does not allow such multiple
inheritance.
Solution: Replace the abstract class DrawableShape
with an Interface Drawable which DrawableCircle implements.

Example of Usage:
DrawableGraph dg;
Drawable d[]
= { DC1, DR1, DC2, DC3, DR2,
}
dg.listarea ( (Shape) d );
d[i].area();
dg.listdraw ( d );
d[i].draw();
Callbacks through Interface
Normal Client-Server
relationship
Note: Server S has no access to clients fields such as x and y.

Problem: How to provide Server limitted access to
clients fields and methods?
Notes: (1)
Argument passing is not feasible:
a.f(x) and b.f(y)
where f(? u){
}.
(2)
Argument
passing may not be enough.
F()
may need to use clients methods.
Solution: Let the client pass itself
to the server with a limitted access window defined by an Interface.

Note: Client
calls Servers f(), which in turn calls
back Clients p().
Example:
interface Updatable {
receive(String x);
};
class Consumer implements Updatable {
Producer source;
String my_text;
Consumer() { source = new Producer (this); };
public receive( String x ) { my_text = x;
};
public change() {
source.prompt();
use
my_text; // consume
};
}
class Producer {
Updatable destination;
String your_text;
Producer (
Updatable you ) { destination = you; };
public prompt() {
your_text
= get_next(); //produce
destination.receive(your_text);
};
}
I Updatable p() receive()
C Consumer S Producer
u destination
a source v you
g() change() f() prompt()