Thursday, September 9, 2010

Code to Understand Objective Anonymous Inner Classes

Courtesy of SCJP Sun® Certified Programmer for Java™ 6 Study Guide Exam (310-065) (9780071591065)




Plain-Old Anonymous Inner Classes, Flavor One


/*
Food has one instance variable p of type Popcorn. However it refers to an anonymous (unnamed) subclass of Popcorn.
Food has no methods.
*/

class Popcorn {
   public void pop() {
      System.out.println("popcorn");
    }
}
class Food {
   Popcorn p = new Popcorn() {
     public void pop() {
        System.out.println("anonymous popcorn");
     }
   }; 

   public static void main(String[] args){
Food f = new Food();
        f.p.pop();
   }
}

Polymorphism is in play when anonymous inner classes are involved



/*
Polymorphism is in play when anonymous inner classes are involved. You can only call methods on an anonymous inner class reference that are defined in the reference variable type! This is no different from any other polymorphic references. The method definition isn’t the problem, though; the real issue is how do you invoke that new method? The reference variable type (the superclass) won’t know anything about that new method (defined in the anonymous subclass), so the compiler will complain if you try to invoke any method on an anonymous inner class reference that is not in the superclass class definition.

Check out the following, illegal code:
*/

class Popcorn {
   public void pop() {
      System.out.println("popcorn");
   }
}

class Food {
   Popcorn p = new Popcorn() {
      public void sizzle() {
        System.out.println("anonymous sizzling popcorn");
      }
      public void pop() {
         System.out.println("anonymous popcorn");
      }
   };

   public void popIt() {
      p.pop();     // OK, Popcorn has a pop() method
      p.sizzle();  // Not Legal! Popcorn does not have sizzle()
   }

   public static void main(String[] args){
      Food f = new Food();
      f.popIt();
   }
}



Plain-Old Anonymous Inner Classes, Flavor Two



/*
Food has instance variable c of type Cookable. c references an anonymous (unnamed) implementor of interface Cookable, rather than an anonymous (unnammed) subclass.

And note that this is the only time you will ever see the syntax

new Cookable()

where Cookable is an interface rather than a nonabstract class type. Because think about it, you can’t instantiate an interface, yet that’s what the code looks like it’s doing. But of course it’s not instantiating a Cookable object, it’s creating an instance of a new, anonymous, implementer of Cookable.
*/

interface Cookable {
   public void cook();
}
class Food {
   Cookable c = new Cookable() {
     public void cook() {
        System.out.println("anonymous cookable implementer");
     }
   };

   public static void main(String[] args){
      Food f = new Food();
      f.c.cook();
   }
}



Argument-Defined Anonymous Inner Classes



/*
We’re calling doStuff() on a Bar object, but the method takes an instance that IS-A Foo, where Foo is an interface. So we must make both an implementation class and an instance of that class, all right here in the argument to doStuff(). So that’s what we do. We write


new Foo() {


to start the new class definition for the anonymous class that implements the Foo interface.
*/

class MyWonderfulClass {
   void go() {
     Bar b = new Bar();
     b.doStuff(new Foo() {
       public void foof() {
         System.out.println("foofy");
       } // end foof method
     }); // end inner class def, arg, and b.doStuff stmt.
   } // end go()
  
   public static void main(String[] args){
      MyWonderfulClass my = new MyWonderfulClass();
      my.go();
   }

} // end class

interface Foo {
   void foof();
}

class Bar {
   void doStuff(Foo f) {f.foof();}
}


No comments:

Post a Comment