Saturday 12 January 2013

Chapter 2: Object Orientation:Implementing an Interface

When you implement an interface, you're agreeing to adhere to the contract defined
in the interface. That means you're agreeing to provide legal implementations
for every method defined in the interface, and that anyone who knows what the
interface methods look like (not how they're implemented, but how they can be
called and what they return) can rest assured that they can invoke those methods on
an instance of your implementing class.

For example, if you create a class that implements the Runnable interface (so
that your code can be executed by a specific thread), you must provide the public
void run() method. Otherwise, the poor thread could be told to go execute your
Runnable object's code and—surprise surprise—the thread then discovers the object
has no run() method! (At which point, the thread would blow up and the JVM
would crash in a spectacular yet horrible explosion.) Thankfully, Java prevents this
meltdown from occurring by running a compiler check on any class that claims
to implement an interface. If the class says it's implementing an interface, it darn
well better have an implementation for each method in the interface (with a few
exceptions we'll look at in a moment).

Assuming an interface, Bounceable, with two methods: bounce(), and
setBounceFactor(), the following class will compile:

public class Ball implements Bounceable
{ // Keyword
   // 'implements'
    public void bounce()
    {
    }

    public void setBounceFactor(int bf)
    {
    }
}


OK, we know what you're thinking: "This has got to be the worst implementation
class in the history of implementation classes." It compiles, though. And runs. The
interface contract guarantees that a class will have the method (in other words,
others can call the method subject to access control), but it never guaranteed a
good implementation—or even any actual implementation code in the body of the
method. The compiler will never say to you, "Um, excuse me, but did you reallymean to put nothing between those curly braces? HELLO. This is a method after all,
so shouldn't it do something?"
Implementation classes must adhere to the same rules for method implementation
as a class extending an abstract class. In order to be a legal implementation class, a
nonabstract implementation class must do the following:

-Provide concrete (nonabstract) implementations for all methods from the
declared interface.
- Follow all the rules for legal overrides.
- Declare no checked exceptions on implementation methods other than
those declared by the interface method, or subclasses of those declared by
the interface method.
- Maintain the signature of the interface method, and maintain the same
return type (or a subtype). (But it does not have to declare the exceptions
declared in the interface method declaration.)

But wait, there's more! An implementation class can itself be abstract! For
example, the following is legal for a class Ball implementing Bounceable:

abstract class Ball implements Bounceable { }

class BeachBall extends Ball
{
    // Even though we don't say it in the class declaration above,
    // BeachBall implements Bounceable, since BeachBall's abstract
    // superclass (Ball) implements Bounceable
    public void bounce()
    {
        // interesting BeachBall-specific bounce code
    }

    public void setBounceFactor(int bf)
    {
        // clever BeachBall-specific code for setting
        // a bounce factor
    }
    // if class Ball defined any abstract methods,
    // they'll have to be
    // implemented here as well.
}

Look for classes that claim to implement an interface but don't provide the
correct method implementations. Unless the implementing class is abstract, the
implementing class must provide implementations for all methods defined in the
interface.
Two more rules you need to know and then we can put this topic to sleep (or put
you to sleep; we always get those two confused):
1. A class can implement more than one interface. It's perfectly legal to say, for
example, the following:

public class Ball implements Bounceable, Serializable, Runnable
{ ... }

You can extend only one class, but implement many interfaces. But remember
that subclassing defines who and what you are,whereas implementing defines a role
you can play
or a hat you can wear, despite how different you might be from some
other class implementing the same interface(but from a different inheritance tree).
For example, a Person extends HumanBeing (although for some, that's debatable).
But a Person may also implement Programmer, Snowboarder, Employee, Parent, or
PersonCrazyEnoughToTakeThisExam.

2. An interface can itself extend another interface, but never implement
anything. The following code is perfectly legal:

public interface Bounceable extends Moveable { } // ok!

Hold on though, because here's where it gets strange. An interface can extend
more than one interface! Think about that for a moment. You know that when we're
talking about classes, the following is illegal:

public class Programmer extends Employee, Geek { } // Illegal!

As we mentioned earlier, a class is not allowed to extend multiple classes in Java.
An interface, however, is free to extend multiple interfaces.

interface Bounceable extends Moveable, Spherical
{ // ok!
    void bounce();

    void setBounceFactor(int bf);
}

interface Moveable
{
    void moveIt();
}

interface Spherical
{
    void doSphericalThing();
}

In the next example, Ball is required to implement Bounceable, plus all methods
from the interfaces that Bounceable extends (including any interfaces those
interfaces extend, and so on until you reach the top of the stack—or is it the bottom
of the stack?). So Ball would need to look like the following:

class Ball implements Bounceable
{
    public void bounce()
    {
    } // Implement Bounceable's methods

    public void setBounceFactor(int bf)
    {
    }

    public void moveIt()
    {
    } // Implement Moveable's method

    public void doSphericalThing()
    {
    } // Implement Spherical
}

If class Ball fails to implement any of the methods from Bounceable, Moveable, or
Spherical, the compiler will jump up and down wildly, red in the face, until it does.
Unless, that is, class Ball is marked abstract. In that case, Ball could choose to
implement any, all, or none of the methods from any of the interfaces, thus leaving
the rest of the implementations to a concrete subclass of Ball, as follows:

abstract class Ball implements Bounceable
{
    public void bounce() { ... } // Define bounce behavior

    public void setBounceFactor(int bf) { ... }
    // Don't implement the rest; leave it for a subclass
}

class SoccerBall extends Ball
{ // class SoccerBall must
// implement the interface methods that Ball didn't
    public void moveIt() { ... }

    public void doSphericalThing() { ... }

    // SoccerBall can choose to override the Bounceable methods
    // implemented by Ball
    public void bounce() { ... }
}

Comparing Concrete and Abstract Examples of Extends and Implements





class Foo { } // OK
class Bar implements Foo { } // No! Can't implement a class
interface Baz { } // OK
interface Fi { } // OK
interface Fee implements Baz { } // No! Interface can't
// implement an interface
interface Zee implements Foo { } // No! Interface can't
// implement a class
interface Zoo extends Foo { } // No! Interface can't
// extend a class
interface Boo extends Fi { } // OK. Interface can extend
// an interface
class Toon extends Foo, Button { } // No! Class can't extend
// multiple classes
class Zoom implements Fi, Fee { } // OK. class can implement
// multiple interfaces
interface Vroom extends Fi, Fee { } // OK. interface can extend
// multiple interfaces
class Yow extends Foo implements Fi { } // OK. Class can do both
// (extends must be 1st)



Burn these in, and watch for abuses in the questions you get on the
exam. Regardless of what the question appears to be testing, the real problem might be
the class or interface declaration. Before you get caught up in, say, tracing a complex
threading flow, check to see if the code will even compile. (Just that tip alone may
be worth your putting us in your will!) (You’ll be impressed by the effort the exam
developers put into distracting you from the real problem.) (How did people manage to
write anything before parentheses were invented?)

Chapter 2: Object Orientation:Reference Variable Casting

It's at the heart of polymorphism
Animal animal = new Dog();

 But what happens when you want to use that animal reference variable to invoke
a method that only class Dog has? You know it's referring to a Dog, and you want to
do a Dog-specific thing? In the following code, we've got an array of Animals, and
whenever we find a Dog in the array, we want to do a special Dog thing. Let's agree
for now that all of this code is OK, except that we're not sure about the line of code
that invokes the playDead method.

class Animal
{
    void makeNoise()
    {
        System.out.println("generic noise");
    }
}

class Dog extends Animal
{
    void makeNoise()
    {
        System.out.println("bark");
    }

    void playDead()
    {
        System.out.println(" roll over");
    }
}

class CastTest2
{
    public static void main(String[] args)
    {
        Animal[] a =
        { new Animal(), new Dog(), new Animal() };
        for (Animal animal : a)
        {
            animal.makeNoise();
            if (animal instanceof Dog)
            {
                animal.playDead(); // try to do a Dog behavior ?
            }
        }
    }
}

When we try to compile this code, the compiler says something like this:
cannot find symbol

The compiler is saying, "Hey, class Animal doesn't have a playDead() method".
Let's modify the if code block:

           if (animal instanceof Dog)
            {
                Dog d = (Dog) animal; // casting the ref. var.
                d.playDead();
            }

The new and improved code block contains a cast, which in this case is
sometimes called a downcast, because we're casting down the inheritance tree to a
more specific class. Now, the compiler is happy.Before we try to invoke playDead,
we cast the animal variable to type Dog. What we're saying to the compiler is, "We
know it's really referring to a Dog object, so it's okay to make a new Dog reference
variable to refer to that object." In this case we're safe because before we ever try the
cast, we do an instanceof test to make sure.

class Animal { }
class Dog extends Animal { }

class DogTest
{
    public static void main(String[] args)
    {
        Animal animal = new Animal();
        Dog d = (Dog) animal; // compiles but fails later
    }
}

It can be maddening! This code compiles! When we try to run it, we'll get an
exception something like this:

java.lang.ClassCastException

Animal animal = new Animal();
Dog d = (Dog) animal;
String s = (String) animal; // animal can't EVER be a String
In this case, you'll get an error something like this:

inconvertible types

Unlike downcasting, upcasting (casting up the inheritance tree to a more general
type) works implicitly (i.e. you don't have to type in the cast) because when you
upcast you're implicitly restricting the number of methods you can invoke, as
opposed to downcasting, which implies that later on, you might want to invoke a
more specific method. For instance:

class Animal
{
}

class Dog extends Animal
{
}

class DogTest
{
    public static void main(String[] args)
    {
        Dog d = new Dog();
        Animal a1 = d; // upcast ok with no explicit cast
        Animal a2 = (Animal) d; // upcast ok with an explicit cast
    }
}

Both of the previous upcasts will compile and run without exception, because a
Dog IS-A Animal, which means that anything an Animal can do, a Dog can do. A
Dog can do more, of course, but the point is—anyone with an Animal reference can
safely call Animal methods on a Dog instance. The Animal methods may have been
overridden in the Dog class, but all we care about now is that a Dog can always do
at least everything an Animal can do. The compiler and JVM know it too, so the
implicit upcast is always legal for assigning an object of a subtype to a reference of
one of its supertype classes (or interfaces). If Dog implements Pet, and Pet defines
beFriendly(), then a Dog can be implicitly cast to a Pet, but the only Dog method
you can invoke then is beFriendly(), which Dog was forced to implement because
Dog implements the Pet interface.

One more thing…if Dog implements Pet, then if Beagle extends Dog, but
Beagle does not declare that it implements Pet, Beagle is still a Pet! Beagle is a Pet
simply because it extends Dog, and Dog's already taken care of the Pet parts of itself,
and all its children. The Beagle class can always override any methods it inherits
from Dog, including methods that Dog implemented to fulfill its interface contract.
And just one more thing…if Beagle does declare it implements Pet, just so that
others looking at the Beagle class API can easily see that Beagle IS-A Pet, without
having to look at Beagle's superclasses, Beagle still doesn't need to implement the
beFriendly() method if the Dog class (Beagle's superclass) has already taken care of
that. In other words, if Beagle IS-A Dog, and Dog IS-A Pet, then Beagle IS-A Pet,
and has already met its Pet obligations for implementing the beFriendly() method
since it inherits the beFriendly() method. The compiler is smart enough to say, "I
know Beagle already IS a Dog, but it's OK to make it more obvious."
So don't be fooled by code that shows a concrete class that declares that it
implements an interface, but doesn't implement the methods of the interface. Before
you can tell whether the code is legal, you must know what the superclasses of this
implementing class have declared. If any class in its inheritance tree has already
provided concrete (i.e., non-abstract) method implementations, and has declared
that it (the superclass) implements the interface, then the subclass is under no
obligation to re-implement (override) those methods.

Animal a = new Dog();
Dog d = (Dog) a;
a.doDogStuff();
Can be replaced with this easy-to-read bit of fun:
Animal a = new Dog();
((Dog)a).doDogStuff();
In this case the compiler needs all of those parentheses, otherwise it
thinks it’s been handed an incomplete statement.


Monday 7 January 2013

Chapter 2: Object Orientation; Overriding / Overloading

Overridden Methods

Any time you have a class that inherits a method from a superclass, you have the
opportunity to override the method (unless, as you learned earlier, the method is
marked final).
The key benefit of overriding is the ability to define behavior that's
specific to a particular subclass type. The following example demonstrates a Horse
subclass of Animal overriding the Animal version of the eat() method:

public class Animal
{
    public void eat()
    {
        System.out.println("Generic Animal Eating Generically");
    }
}

class Horse extends Animal
{
    public void eat()
    {
        System.out.println("Horse eating hay, oats, " + "and horse treats");
    }
}

For abstract methods you inherit from a superclass, you have no choice.
You must implement the method in the subclass unless the subclass is also abstract.
Abstract methods must be implemented by the concrete subclass, but this is a lot like saying
that the concrete subclass overrides the abstract methods of the superclass. So you
could think of abstract methods as methods you're forced to override.

public class TestAnimals
{
    public static void main(String[] args)
    {
        Animal a = new Animal();
        Animal b = new Horse(); // Animal ref, but a Horse object
        a.eat(); // Runs the Animal version of eat()
        b.eat(); // Runs the Horse version of eat()
    }
}

class Animal
{
    public void eat()
    {
        System.out.println("Generic Animal Eating Generically");
    }
}

class Horse extends Animal
{
    public void eat()
    {
        System.out.println("Horse eating hay, oats, " + "and horse treats");
    }

    public void buck()
    {
    }
}


Animal c = new Horse();
c.buck(); // Can't invoke buck();
// Animal class doesn't have that method

public class TestAnimals
{
    public static void main(String[] args)
    {
        Horse h = new Horse();
        h.eat(); // Not legal because Horse didn't inherit eat()
    }
}

class Animal
{
    private void eat()
    {
        System.out.println("Generic Animal Eating Generically");
    }
}

class Horse extends Animal
{
}

Invoking a Superclass Version of an Overridden Method

public class Animal
{
    public void eat()
    {
    }

    public void printYourself()
    {
        // Useful printing code goes here
    }
}

class Horse extends Animal
{
    public void printYourself()
    {
        // Take advantage of Animal code, then add some more
        super.printYourself(); // Invoke the superclass
        // (Animal) code
        // Then do Horse-specific
        // print work here
    }
}

class Animal {
public void eat() throws Exception {
// throws an Exception
}
}
class Dog2 extends Animal {
public void eat() { // no Exceptions }
public static void main(String [] args) {
Animal a = new Dog2();
Dog2 d = new Dog2();
d.eat(); // ok
a.eat(); // compiler error -
// unreported exception
}
}

This code will not compile because of the Exception declared on the
Animal eat() method. This happens even though, at runtime, the eat() method used
would be the Dog version, which does not declare the exception.

Overloaded Methods

Overloaded methods let you reuse the same method name in a class, but with
different arguments (and optionally, a different return type). Overloading a method
often means you're being a little nicer to those who call your methods, because your
code takes on the burden of coping with different argument types rather than forcing
the caller to do conversions prior to invoking your method.

The rules are simple:
- Overloaded methods MUST change the argument list.
- Overloaded methods CAN change the return type.
- Overloaded methods CAN change the access modifier.
- Overloaded methods CAN declare new or broader checked exceptions.

class Animal {
}

class Horse extends Animal {
}

class UseAnimals {
    public void doStuff(Animal a) {
        System.out.println("In the Animal version");
    }

    public void doStuff(Horse h) {
        System.out.println("In the Horse version");
    }

    public static void main(String[] args) {
        UseAnimals ua = new UseAnimals();
        Animal animalObj = new Animal();
        Horse horseObj = new Horse();
        ua.doStuff(animalObj);
        ua.doStuff(horseObj);
    }
}

The output is what you expect:
in the Animal version
in the Horse version

Polymorphism in Overloaded and Overridden Methods

public class Animal {
    public void eat() {
        System.out.println("Generic Animal Eating Generically");
    }
}

public class Horse extends Animal {
    public void eat() {
        System.out.println("Horse eating hay ");
    }

    public void eat(String s) {
        System.out.println("Horse eating " + s);
    }
}
Notice that the Horse class has both overloaded and overridden the eat()
method. Table 2-2 shows which version of the three eat() methods will run
depending on how they are invoked.


Don’t be fooled by a method that’s overloaded but not overridden by a
subclass. It’s perfectly legal to do the following:
public class Foo {
void doStuff() { }
}
class Bar extends Foo {
void doStuff(String s) { }
}
The Bar class has two doStuff() methods: the no-arg version it inherits
from Foo (and does not override), and the overloaded doStuff(String s) defined in the
Bar class. Code with a reference to a Foo can invoke only the no-arg version, but code
with a reference to a Bar can invoke either of the overloaded versions.