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 client’s fields such as x and y.

 

 


Problem:    How to provide Server limitted access to client’s 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 client’s methods.


 

Solution:   Let the client pass itself to the server with a limitted access window defined by an Interface.

 

 


 

 

 

 


Note:  Client calls Server’s  f(), which in turn calls back Client’s  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()