Interfaces Question - I am missing something

J

jmDesktop

I'm trying to understand the benefit of interfaces (the oop kind). I
understand that:

they allow different types of objects to be grouped by behavior
instead of relying strictly on inheritance (a kind of multi-
inheritance)

They allow for more polymorphism, as opposed to just inheritance.

What I don't understand (please correct the above if I am wrong
thanks), is why I need them. I'm just missing something obvious.

I was almost getting it here:

http://www.artima.com/objectsandjava/webuscript/PolymorphismInterfaces1.html

In the middle of the page it has Interfaces. It talks about things
being "Washable." It shows some hideous code of what you'd have to do
if you didn't use Interfaces (lots of if else ifs):

// In Source Packet in file interface/ex2/Cleaner.java
class Cleaner {

// (This doesn't use polymorphism)
public static void cleanAnObject(Object obj) {

// Perform any necessary processing of the
// object before washing...

// Wash the object
if (obj instanceof Cup) {
// (Here you are using polymorphism, but just
// within the Cup family.)
((Cup) obj).wash();
}
else if (obj instanceof Dog) {
((Dog) obj).wash();
}
else if (obj instanceof Window) {
((Window) obj).wash();
}
else if (obj instanceof Car) {
((Car) obj).wash();
}
// Else the object doesn't get washed

// Perform other processing on the object to
// complete the cleaning process...
}
}

In the end is the payoff with:

// In Source Packet in file interface/ex3/Cleaner.java
class Cleaner {
public static void cleanAnObject(WashableObject wo) {
//...
wo.wash();
//...
}
}


Now, what I don't get is why this is so great. I understand it looks
better than the else if construct and the JVM calls the individual
classes that implement the behavior that are of the Washable "type"
interface, with there methods in a cleaner way, but...You still have
to create a wash() method for each class that wo.wash() calls, so how
did I make out better? I just got rid of the ugly code for the OOP
design, but why? I think it has to do with extensibility because if
someone added to the program they would need another if else added to
the ugly code. I don't believe it's just because it's OOP for the
sake of OOP. I'm missing it.

I keep reading it is a contract, but how? What couldn't a designer
just create a wash2() method and do something there. How did it help?

Thank you for helping me.
 
J

jmDesktop

I'm trying to understand the benefit of interfaces (the oop kind).  I
understand that:

they allow different types of objects to be grouped by behavior
instead of relying strictly on inheritance (a kind of multi-
inheritance)

They allow for more polymorphism, as opposed to just inheritance.

What I don't understand (please correct the above if I am wrong
thanks), is why I need them.  I'm just missing something obvious.

I was almost getting it here:

http://www.artima.com/objectsandjava/webuscript/PolymorphismInterface...

In the middle of the page it has Interfaces.  It talks about things
being "Washable."  It shows some hideous code of what you'd have to do
if you didn't use Interfaces (lots of if else ifs):

// In Source Packet in file interface/ex2/Cleaner.java
class Cleaner {

    // (This doesn't use polymorphism)
    public static void cleanAnObject(Object obj) {

        // Perform any necessary processing of the
        // object before washing...

        // Wash the object
        if (obj instanceof Cup) {
            // (Here you are using polymorphism, but just
            // within the Cup family.)
            ((Cup) obj).wash();
        }
        else if (obj instanceof Dog) {
            ((Dog) obj).wash();
        }
        else if (obj instanceof Window) {
            ((Window) obj).wash();
        }
        else if (obj instanceof Car) {
            ((Car) obj).wash();
        }
        // Else the object doesn't get washed

        // Perform other processing on the object to
        // complete the cleaning process...
    }

}

In the end is the payoff with:

// In Source Packet in file interface/ex3/Cleaner.java
class Cleaner {
    public static void cleanAnObject(WashableObject wo) {
        //...
        wo.wash();
        //...
    }

}

Now, what I don't get is why this is so great.  I understand it looks
better than the else if construct and the JVM calls the individual
classes that implement the behavior that are of the Washable "type"
interface, with there methods in a cleaner way, but...You still have
to create a wash() method for each class that wo.wash() calls, so how
did I make out better?  I just got rid of the ugly code for the OOP
design, but why?  I think it has to do with extensibility because if
someone added to the program  they would need another if else added to
the ugly code.  I don't believe it's just because it's OOP for the
sake of OOP.  I'm missing it.

I keep reading it is a contract, but how?  What couldn't a designer
just create a wash2() method and do something there.  How did it help?

Thank you for helping me.

If I have to instantiate my new classes anyway, say:

Dog d = new Dog()
Cat c = new Cat()
Truck t = new Truck()

Why could I just call:

d.wash();
c.wash();
t.wash();

in my program? Why would I want to send them to something like:

// In Source Packet in file interface/ex7/Cleaner.java
class Cleaner {
public static void cleanAnObject(Washable washMe) {
//...
washMe.wash();
//...
}
}

I'm not even sure how I'd send it, however, to class Cleaner
cleanAnObject and maybe that is the problem. Thanks again.
 
D

Daniel Pitts

jmDesktop said:
If I have to instantiate my new classes anyway, say:

Dog d = new Dog()
Cat c = new Cat()
Truck t = new Truck()

Why could I just call:

d.wash();
c.wash();
t.wash();

in my program? Why would I want to send them to something like:

// In Source Packet in file interface/ex7/Cleaner.java
class Cleaner {
public static void cleanAnObject(Washable washMe) {
//...
washMe.wash();
//...
}
}

I'm not even sure how I'd send it, however, to class Cleaner
cleanAnObject and maybe that is the problem. Thanks again.

The real benefit comes from the fact that now ANYONE can create a
Washable object, and your cleanAnObject doesn't have to know about the
new class type!

Imaging Collections.sort() having to have an
if (a instanceof String and b instanceof String)
comparison = ((String)a).compareTo((String)b);
else if (a instanceof Integer and b instanceof Integer)
comparison = ((Integer)a).compareTo((Integer)b);
....
else if (a instanceof MyUserTypeNumberThreeHundred and b instanceof
MyUserTypeNumberThreeHundred)
comparison =
((MyUserTypeNumberThreeHundred)a).compareTo((MyUserTypeNumberThreeHundred)b);

Instead, it can simply use a Comparable object.


There are plenty of other good examples.
 
M

Mark Space

jmDesktop said:
In the middle of the page it has Interfaces. It talks about things
being "Washable." It shows some hideous code of what you'd have to do
if you didn't use Interfaces (lots of if else ifs):

I agree that's a pretty bad example. How about something that Java
actually uses:

public interface Comparable {
int compareTo( Object o );
}

(Note: typed from memory, and I'm ignoring generics to make the example
simple.)

Here's a simple example. I happen to know that the String class
implements comparable, so I can use that class.


package bubblesort;

public class Main {

public static void main(String[] args) {
String[] sortMe = {"B", "Z", "A", "D"};
sort((Comparable[]) sortMe);
for (String s : sortMe) {
System.out.println(s);
}
}

static void sort(Comparable[] list) {
boolean sorted;
for (int i = 0; i < list.length - 1; i++)
{
sorted = true;
for (int j = 0; j < list.length - 1 - i; j++)
{
if (list[j].compareTo(list[j + 1]) > 0) // The Pay-off
{
Comparable temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
sorted = false;
}
}
if (sorted) {
return;
}
}
return;
}
}


And it sorts anything that implements "Comparable". In this routine,
calling list[j].compareTo() is the same "pay off" that calling wash()
gives you, with a bit more practical application.

Being Washable may not be all that important, but I hope you can see
that Comparable sure is. And future class you define, you can make
Comparable and sort with this one routine (and of course both arrays and
Collections have sorting already, based on Comparable. No need to write
your own at all.)

If not for Comparable, you'd have to write your own sort routine for
each type you create, as Peter says. Now wouldn't that be a pain?
 
J

jmDesktop

jmDesktop said:
In the middle of the page it has Interfaces.  It talks about things
being "Washable."  It shows some hideous code of what you'd have to do
if you didn't use Interfaces (lots of if else ifs):

I agree that's a pretty bad example.  How about something that Java
actually uses:

public interface Comparable {
   int compareTo( Object o );

}

(Note: typed from memory, and I'm ignoring generics to make the example
simple.)

Here's a simple example.  I happen to know that the String class
implements comparable, so I can use that class.

package bubblesort;

public class Main {

     public static void main(String[] args) {
         String[] sortMe = {"B", "Z", "A", "D"};
         sort((Comparable[]) sortMe);
         for (String s : sortMe) {
             System.out.println(s);
         }
     }

     static void sort(Comparable[] list) {
         boolean sorted;
         for (int i = 0; i < list.length - 1; i++)
         {
             sorted = true;
             for (int j = 0; j < list.length - 1 - i; j++)
             {
               if (list[j].compareTo(list[j + 1]) > 0) // The Pay-off
               {
                   Comparable temp = list[j];
                   list[j] = list[j + 1];
                   list[j + 1] = temp;
                   sorted = false;
               }
             }
             if (sorted) {
                 return;
             }
         }
         return;
     }

}

And it sorts anything that implements "Comparable". In this routine,
calling list[j].compareTo() is the same "pay off" that calling wash()
gives you, with a bit more practical application.

Being Washable may not be all that important, but I hope you can see
that Comparable sure is.  And future class you define, you can make
Comparable and sort with this one routine (and of course both arrays and
Collections have sorting already, based on Comparable.  No need to write
your own at all.)

If not for Comparable, you'd have to write your own sort routine for
each type you create, as Peter says. Now wouldn't that be a pain?

Ok. Thanks (to everyone.) But where is the compareTo() logic from
here:

if (list[j].compareTo(list[j + 1]) > 0) // The Pay-off

I understand that compareTo implements Comparable and therefore any
item that is a Comparable type can be passed to it, but how do I know
what compareTo really does? Beyond the signature in the Interface.
The docs I read said it took a String str, but what if I had numbers?
I'm probably straying from the original point, but the "real"
compareTo method lives somewhere and has a whole lot of code in it,
right?
 
L

lscharen

I understand that compareTo implements Comparable and therefore any

You're confusing your terminology a bit here. compareTo does not
implement Comparable, rather any object that implements the Comparable
interface must has a method called compareTo(Object other).
item that is a Comparable type can be passed to it, but how do I know
what compareTo really does? Beyond the signature in the Interface.

You don't know what it really does and that is the whole point of
using an interface! As long as the class that implements the
compareTo() method adheres to the documented behavior, then any method
that takes a Comparable object will work with an instance of any class
that implements Comparable.
The docs I read said it took a String str, but what if I had numbers?
I'm probably straying from the original point, but the "real"
compareTo method lives somewhere and has a whole lot of code in it,
right?

No. The "real" code is usually very short and exists as a specialized
routine for each class. Let me give you a concrete example with a
String-like class, an Integer-like class and a couple custom classes.
I am using the Generics parameterization, but don't let that throw
you.

I hope you can see that it is much easier to develop a compareTo
function for an object *within that class* rather than trying to write
some uber-compareTo() that knows about every object ever written.

Also, notice that you often want to impose different orderings on the
same underlying class. That is why many of the Collections classes
(like TreeSet) have a constructor that takes a Comparator object, that
way you can use a different compareTo method without having to
override anything.

/**
* Example 1
*/
public class MyString implements Comparable<MyString>
{
private char[] chars;
...

public int compareTo( MyString other )
{
// This compareTo function imposes an order on strings up to
the
// length of the shorter string
for ( int i = 0; i < Math.min( chars.length,
other.chars.length ); i++ ) {
if ( chars < other.chars )
return -1;
if ( chars > other.chars )
return 1;
}

// strings are equal
return 0;
}
}

/**
* Example 2
*/
public class MyInteger implements Comparable<MyInteger>
{
private int value;
...

public int compareTo( MyInteger other )
{
// This orders the integers from low to high
return value - other.value;
}
}

/**
* Example 3 : This is a Set-like class and sets are ordered by size
*/
public class MySet implements Comparable<MySet>
{
private Set theSet;
...

public int compareTo( MySet other )
{
// This orders the sets from smallest to largest
return theSet.size() - other.theSet.size();
}
}

/**
* Example 4 : Another Integer class, but now we sort by the number of
ones in the
* binary representation of the integer
*/
public class MyInteger2 implements Comparable<MyInteger2>
{
private int value;
...

public int compareTo( MyInteger2 other )
{
// Think about this one....it's good for you.
return Intger.bitCount( value ) -
Integer.bitCount( other.value );
}
}
 
M

Mark Space

jmDesktop said:
I understand that compareTo implements Comparable and therefore any
item that is a Comparable type can be passed to it, but how do I know
what compareTo really does? Beyond the signature in the Interface.
The docs I read said it took a String str, but what if I had numbers?
I'm probably straying from the original point, but the "real"
compareTo method lives somewhere and has a whole lot of code in it,
right?

Ischaren gave some pretty good examples how compareTo might actually
work. One of the important things about Java is that it's pretty
unmysterious. Most things can be implemented in a straight-forward way
and they will work correctly. The language rarely has to go behind your
back and implement things in ways that you cannot.


I'll give a simpler and more literal answer. First, use Google. Google
for "java <classname> se 6" will almost always give you the most recent
Java docs.

"java Comparable se 6" gives me:

<http://java.sun.com/javase/6/docs/api/java/lang/Comparable.html>

as the first result. Scroll down that page and you'll get the
documentation for compareTo(). It's a little obtuse, but some
experimentation should sharpen your understanding.

For the compareTo() for String, Google again. This time I have to use
the full class name because "String" is just too common of a word.

"java.lang.String se 6"

<http://java.sun.com/javase/6/docs/api/java/lang/String.html#compareTo(java.lang.String)>

This will tell you what the String's version of compareTo() really does.
It's pretty plain and straight forward.


Finally, don't over look the Java tutorial:

<http://java.sun.com/docs/books/tutorial/>

I like the Javapassion website for beginners.

<http://www.javapassion.com/>

For books, I recommend _Learning Java_ by O'Reilly. It's somewhat
thick, but there's a surprising amount of good information in there,
enough to serve as a reference on many topics long after you are don't
learning the basics. It's discussion of generics is especially good.
 
P

Patricia Shanahan

jmDesktop wrote:
....
Ok. Thanks (to everyone.) But where is the compareTo() logic from
here:

if (list[j].compareTo(list[j + 1]) > 0) // The Pay-off

I understand that compareTo implements Comparable and therefore any
item that is a Comparable type can be passed to it, but how do I know
what compareTo really does? Beyond the signature in the Interface.
The docs I read said it took a String str, but what if I had numbers?
I'm probably straying from the original point, but the "real"
compareTo method lives somewhere and has a whole lot of code in it,
right?

I think what you are missing is the sheer power of Java's method
invocation. There is no one "real" compareTo. There are thousands of
compareTo implementations. I've written several, and I expect most
programmers who have written any significant amount of code in Java
would say the same. The API documentation for Comparable lists dozens of
known implementing classes just in the core libraries.

Each class that implements Comparable either declares or inherits a
compareTo that is the "real" compareTo if list[j] is an instance of that
class.

Patricia
 
J

jmDesktop

I think what you're missing about interfaces is the scenario where
you want to use them.

The code you posted above already knows that there are three objects
and that they are different types.  It knows that one is a Dog, one
is a Cat, and one is a Truck.  It doesn't need interfaces because it
is already aware of what class every object is.  After all, it is the
one who has created the objects, so of course it knows what class
they are.

But that is not always how it works.  Let me flesh out your example.
I'm going to say there's a guy named Bob, and he manages his life
all on his own.  The class that represents Bob looks like this:

     class Bob {
         Dog d;
         Cat c;
         Truck t;

         void obtainWorldlyPossessions() {
             d = new Dog();
             c = new Cat();
             t = new Truck();
         }

         void saturdayChores() {
             d.wash();
             c.wash();
             t.wash();
         }
     }

When Bob is doing his chores on Saturday, he can wash his dog and
cat and truck, and he doesn't need an interface because he knows
all about his possessions.

Now suppose Bob wants to go out of town and he wants to hire someone
to take care of his pets while he's gone.  You could certainly
create a custom pet sitter class that knows how to deal with Bob's
stuff specifically:

     class BobPetSitter {
         void watchBobsPets(Bob bob) {
             bob.d.wash();
             bob.c.wash();
         }
     }

Then Bob can arrange to have his pets cared for like this:

     // (a method in class Bob...)
     void prepForVacation() {
         BobPetSitter sitter = new BobPetSitter();
         sitter.watchBobsPets(this);
     }

But you can see this class is only useful for Bob's pets.  Maybe
you want to go into business and create a PetSitter that can
wash anyone's pets.  Your PetSitter class wants to be able to get
as much business as possible, so if the pets contain their own
wash() method, you'd like to be able to support washing any kind
of pet, without special knowledge for each one.  If you get a
potential customer who has a pet emu, you want to be able to wash
that emu, not throw up your hands and say, "I can't wash emus,
so I can't take this job.  I could learn to wash emus, but that's
complicated."  No, you want to be able to say, "If it's a pet,
I can handle it."

So, let's change the scenario and say that Cat and Dog and Emu all
implement the Pet interface:

     interface Pet {
         void wash();
     }

Then we can make a PetSitter than can wash any type of pet (and
multiple ones):

     class PetSitter {
         List<Pet> pets = new ArrayList<Pet>();

         void addPet(Pet pet) {
             pets.add(pet);
         }

         void washAllPets() {
             for (Pet p : pets) {
                 p.wash();
             }
         }
     }

Now Bob can arrange a pet sitter like this instead:

     // (a method in class Bob...)
     void prepForVacation() {
         PetSitter sitter = new PetSitter();
         sitter.addPet(d);
         sitter.addPet(c);
     }

The great thing about PetSitter class is that now it can take any
customer.  It doesn't need any knowledge at all of what kind of
pets it's washing.  It doesn't need to know how many.  It can wash
a new type of pet it has never heard of before.

The reason that this matters is that PetSitter is not very closely
associated with Bob.  It has a casual, loose relationship.  Bob
might like to hire a different PetSitter next time that has a
better price.  And somebody who owns an Emu can hire this same
PetSitter to wash it, even though the PetSitter washes different
types of Pets for Bob.

The point is that the Pet interface has allowed the PetSitter
to see all pets as equivalent, because there is no reason that
the PetSitter needs to know the difference.  Bob needs to know
the differences because he created the pet objects, and he knows
what kinds of pets he wants and why, but the PetSitter doesn't
need to know this stuff just to wash the pets.  The interface
allows PetSitter to ignore the difference it doesn't care about
(that it would be wasteful and pointless to care about) and focus
on the commonalities that it does care about.

Side notes:
(1) Yes, pets need to be fed too.  Ignored for simplicity.
(2) Even though Truck has a wash() method, I didn't call it
a pet.  I assumed its meaning of wash() might be different
somehow.  But you could take it a step further and generalize
and create an interface called Washable.

   - Logan

Thank you. I understand. I had also looked at several other
explanations. I think what many explanations miss is code that has
iteration involved. They explain, but don't get any scenarios where
it might be helpful. You did and thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top