Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / July 2005

Tip: Looking for answers? Try searching our database.

Multiple Inheritance with Interfaces

Thread view: 
Will - 15 Jul 2005 14:39 GMT
You cannot inherit from more than one super class in Java, but
according to all the texts 'Interfaces allow you to 'inherit' from
more than one class'. But all an interface gives you is a method name
so how on earth does an Interface allow you to use methods from other
classes -  a method name is just a name. Pls don't refer to 'contracts'
as I have read too much about them over and over.
Any kind clever person can explain in words on one syllable?
danmcleran@yahoo.com - 15 Jul 2005 14:53 GMT
The only thing that comes to mind is to have your class use composition
to implement the desired behaviour. Something like this (say you want a
class that 'inherits' both Foo and Bar functionality, you do this by
holding instances A and B which implement Foo and Bar, respectively):

public interface Foo {
   public void saySomething();
}

public interface Bar {
   public void saySomethingElse();
}

public class A implements Foo {

   /* (non-Javadoc)
    * @see Foo#saySomething()
    */
   public void saySomething() {
       System.out.println("A says something");
   }

}

public class B implements Bar {

   /* (non-Javadoc)
    * @see Bar#saySomethingElse()
    */
   public void saySomethingElse() {
       System.out.println("B says something else");
   }

}

public class C implements Foo, Bar {

   private final A a_ = new A();
   private final B b_ = new B();

   /* (non-Javadoc)
    * @see Foo#saySomething()
    */
   public void saySomething() {
       this.a_.saySomething();
   }

   /* (non-Javadoc)
    * @see Bar#saySomethingElse()
    */
   public void saySomethingElse() {
       this.b_.saySomethingElse();
   }

}
Will - 15 Jul 2005 20:30 GMT
Hello Damncl, this seems to work without any interface.
See my re-write of class C with NO IMPLEMENTS, it works
just the same. We just instantiate an object for class A
(& B) and call its method. I don't see what the Interface
buys you (where is anything remotely like MI?)
I know I am missing the point, but I just don't get it
(Interfaces & MI that is).

Here is the code (I have compiled and run it, - no errors)

public class C  {   //

private final A a_ = new A();  // works without an interface at all!??
private final B b_ = new B();
   /* (non-Javadoc)
    * @see Foo#saySomething()
    */
public static void main(String [] ds) {
A aa = new A();
aa.saySomething(); // calls method from class A without the interface

    }

   public void saySomething() {
   this.a_.saySomething();
   }

   /* (non-Javadoc)
    * @see Bar#saySomethingElse()
    */
   public void saySomethingElse() {
   this.b_.saySomethingElse();
   }
}

public class B implements Bar {

   /* (non-Javadoc)
    * @see Bar#saySomethingElse()
    */
   public void saySomethingElse() {
       System.out.println("B says something else");
   }

}
public class A implements Foo {

   /* (non-Javadoc)
    * @see Foo#saySomething()
    */
   public void saySomething() {
       System.out.println("A says something");
   }
}
public interface Foo {
   public void saySomething();
}

public interface Bar {
   public void saySomethingElse();
}

The Interfaces Foo and Bar do not
appear to allow class C to MI or
'inherit' from class A and class B.
I know about contracts, but where
does any form of multiple inheritance
come in to it? I thought that if you
had a pet class and a animalclass that
a dog class could 'inherit' from both
by using an Interface?
I don't get it (but I am a bit dumb)
danmcleran@yahoo.com - 15 Jul 2005 21:22 GMT
Of course you could do this without implementing these interfaces, but
if you are trying to mimic multiple inheritance and some other software
construct is expecting a class that implements Foo and yet another
construct is expecting a class that implements Bar, one could implement
both in the same class, i.e. class C. Although class C does not
'extend' class A (i.e. Foo) and class B (i.e. Bar), it implements both
interfaces (Foo and Bar) and uses composition to behave like it does
(i.e. give the appearance of multiple inheritance of classes A & B).

Here is a modified version of main:

public class Main {

   public static void doSomethingWithAClassThatIsAFoo(final Foo f) {
       f.saySomething();
   }

   public static void doSomethingWithAClassThatIsABar(final Bar b) {
       b.saySomethingElse();
   }

   public static void main(String[] args) {
       C test = new C();

       doSomethingWithAClassThatIsABar(test);
       doSomethingWithAClassThatIsAFoo(test);
   }
}
Will - 16 Jul 2005 12:25 GMT
Hello Damec
I ran your code and saw that passing an Interface
type object indeed ran the correct methods, but
these methods were composed from instantation of
objects. So I removed all the interfaces and
ran  the same code with thae same result. Here is
the code:

public interface Foo { // not used
   public void saySomething();
}
public interface Bar { // not used
   public void saySomethingElse();
}

public class A  { // removed implements

   public void saySomething() {
   System.out.println("A says something");
   }
}

public class B  { // removed implements
   public void saySomethingElse() {
   System.out.println("B says something else");
   }
}

public class C   { // removed implements

   private A a_ = new A();
   private B b_ = new B();
   public void saySomething() {
       this.a_.saySomething();
   }
   public void saySomethingElse() {
       this.b_.saySomethingElse();
   }
}

public class Main {

// now f is a C
public static void doSomethingWithAClassThatIsAFoo(C f) {
       f.saySomething();
   }
// now b is a C
 public static void doSomethingWithAClassThatIsABar(C b) {
       b.saySomethingElse();
   }

public static void main(String[] args) {
      C test = new C();

       doSomethingWithAClassThatIsABar(test);
       doSomethingWithAClassThatIsAFoo(test);
   }
}
OUTPUT:
B says something else
A says something
Press any key to continue...

I must be the only one that does not
understand this, I can see that a
foo Interface object does the trick,
but it is still using good old
instantiation of classes A & B to get
at the method implementations in A & C
& I can do this anyway (MI, Interface or
not). I just do an instantation & method
call. The Interface seems to do nothing
to help except we write more code. And
how come real interfaces actually do stuff
like compare objects and run threads. Is
it method call backs and messaging?
Maybe its something so simple that I just
cant see it. I have tried & tried to grasp it.
blmblm@myrealbox.com - 16 Jul 2005 15:25 GMT
>Hello Damec
>I ran your code and saw that passing an Interface
[quoted text clipped - 46 lines]
>        b.saySomethingElse();
>    }

Um ....

Changing the type of the parameter (from Foo for the first
function, and Bar for the section, to C in both cases) takes
away the point of the example.

The method doSomethingWithAClassThatIsAFoo() will presumably
do something sensible as long as the parameter it is passed
belongs to a class with a saySomething() method.  An object
of class C will work, but so would an object of class A,
right?  but by making the type of the parameter C, you make
it impossible to call this method with a parameter of type A,
even though that would (presumably) be a sensible thing to do.

To indicate that doSomethingWithAClassThatIsAFoo() should
accept objects of any class that has a saySomething() method,
the original code defines an interface Foo containing that
method.  If classes A and C are declared to "implement Foo",
this means that:

(1) Both A and C need to have a saySomething() method.

(2) You can pass an object that's a C (e.g., "test" in main
below) to doSomethingWithAClassThatIsAFoo(), but you could
also pass it an A, as in the following (untested!!) lines:

   A testA = new A();
   doSomethingWithAClassThatIsAFoo(testA);

You could also define other classes with saySomething() methods,
totally unrelated to A and C, and then pass objects of these
classes to doSomethingWithAClassThatIsAFoo().  The only requirement
is that the class have a saySomething() method, which you indicate
by saying that the class "implements Foo".

Well, I don't know if this is getting clearer or murkier ....

> public static void main(String[] args) {
>       C test = new C();
[quoted text clipped - 23 lines]
>Maybe its something so simple that I just
>cant see it. I have tried & tried to grasp it.

I also think there must be something very simple that would make all
of this clear to you, because I don't think the basic ideas should
be beyond someone who has mastered *some* programming language
(as it sounds like you have).  There must be someone reading this
group who can say the magic words that will make the light bulb
come on for you, but ....

I think a lot of the responses you're getting are bringing in lots
of details and complications that while interesting and relevant
probably just confuse you further.

It might help also if you described your previous programming
experience, particularly which language(s) you've used before.
(I thought this might be in one of your earlier posts, but I didn't
find it.  Apologies if I just missed it.)

| B. L. Massingill
| ObDisclaimer:  I don't speak for my employers; they return the favor.
Thomas G. Marshall - 16 Jul 2005 23:30 GMT
blmblm@myrealbox.com coughed up:

...[rip]...

> I also think there must be something very simple that would make all
> of this clear to you, because I don't think the basic ideas should
> be beyond someone who has mastered *some* programming language
> (as it sounds like you have).  There must be someone reading this
> group who can say the magic words that will make the light bulb
> come on for you, but ....

I've seen similar disconnects, and it usually comes from a very deep
assumption formed somewhere in the learning process.  That low level
assumption is incorrect, yet remains the stake in the sand from which all
new knowledge is measured.

It gets very tricky for people when that assumption proves to be 90%
correct.  I'm not sure what that assumption is for the OP just yet.

...[rip]...

Signature

Sometimes life just sucks and then you live.

Dan McLeran - 16 Jul 2005 17:21 GMT
I hope this isn't duplicated, but I'm not seeing my earlier post.
Anyway, by changing the method signature of the example, you've
defeated the purpose of the exercise. The original example had methods
that expected arguments of Foo and Bar. What this was doing was forcing
the passed arguments to implement the Foo or Bar interfaces. Our class,
class C, implemented both of these interfaces and so could be passed to
each method. Class C provided the look and feel of multiple inheritance
of classes A and B by implementing these interfaces and holding its own
copies of A and B. In Java, you cannot extend 2 base classes:

class C extends A,B // won't compile.

My suggestion was to provide interfaces and a class per interface that
you wish class C to extend. Then instead of extending A and B, you
implement each interface and hold instances of A and B, which receive
the forwarded method calls.

Maybe a different example will help you. Let's create a small example
where a fire house has employees, one of which is a dog. We create an
interface, IAnimal, to describe animal behaviour. We also create an
interface, IEmployee, to describe employee behaviour. We have an Animal
class that can be extended and an Employee class which can be extended.
We will create a WorkingDogHolder class to 'extend' both Animal and
Employee by implementing both the IAnimal and IEmployee interfaces and
holding instances of Dog and Employee. We will create a Secretary class
to pay employees and a Groomer class to groom animals. Because a
WorkingDogHolder is both and Animal and an Employee, we need to try and
fake some multiple inheritance:

public interface IAnimal {
   public void eat();
   public void receiveGrooming();
}

public interface IEmployee {
   public void receivePayment();
}

public class Animal implements IAnimal {

   /* (non-Javadoc)
    * @see IAnimal#eat()
    */
   public void eat() {
       System.out.println("Animals love to eat!");
   }

   public void receiveGrooming() {
       System.out.println("Animals love a good grooming");
   }
}

public class Dog extends Animal {
   public void eat() {
       System.out.println("Dogs love to eat!");
   }

   public void receiveGrooming() {
       System.out.println("Dogs love a good grooming");
   }
}

public class Employee implements IEmployee {

   /* (non-Javadoc)
    * @see IEmployee#receivePayment()
    */
   public void receivePayment() {
       System.out.println("I love payday!");
   }
}

public class WorkingDogHolder implements IAnimal, IEmployee {
   private final Employee employee_ = new Employee();
   private final Dog dog_ = new Dog();

   public void receivePayment() {
       this.employee_.receivePayment();
       this.eat();
   }

   public void eat() {
       this.dog_.eat();
   }

   public void receiveGrooming() {
       this.dog_.receiveGrooming();
   }
}

public class Groomer {
   public void groomAnimal(final IAnimal animal) {
       animal.receiveGrooming();
   }
}

public class Secretary{
   public void providePayment(final IEmployee employee) {
       employee.receivePayment();
   }
}

public class Main {

   public static void main(String[] args) {
       Employee humanEmployee = new Employee();
       WorkingDogHolder workingDog = new WorkingDogHolder();
       Dog normalDog = new Dog();
       Secretary secretary = new Secretary();
       Groomer groomer = new Groomer();

       secretary.providePayment(humanEmployee);
       secretary.providePayment(workingDog);
       //secretary.providePayment(normalDog);    //won't compile because
a normal dog

       //doesn't get paid
       groomer.groomAnimal(normalDog);
       groomer.groomAnimal(workingDog);
       //groomer.groomAnimal(humanEmployee);    //won't compile because a
human

           //can't be groomed in this example
   }
}
Thomas G. Marshall - 17 Jul 2005 00:14 GMT
Will coughed up:
> Hello Damec
> I ran your code and saw that passing an Interface
> type object indeed ran the correct methods, but
> these methods were composed from instantation of
> objects.

...[rip]...

Would you mind if we start at the beginning with what interfaces are, but in
a more example-driven way, rather than hoity toity theory?  This is going to
be very basic, and hopefully not insult you.  But I think there is a
misunderstanding somwhere in here.  Then you can tell me to what extent you
understand what I have to say, so we can procede from there.

Let's start with modeling a bunch of creatures.

Let's pretend that I want to model birds.  They know how to fly a certain
number of feet.  They also know how to chirp.  We'll leave the details of
how flight and chirping is actually accomplished out of the discussion /on
purpose/.  Note this is a real class, not an interface.

public class Bird extend Creature
{
   public void fly(int feet) { /* fly code here */ }
   public void chirp() { /* chirping code here */ }
}

Now let's pretend that we also have Bugs.  They know how to fly, but they
don't know much about chirping, but they can sure run.  Birds can't really
run.

public class Bug extend Creature
{
   public void fly(int feet) { /* fly code here */ }
   public void run(int feet) { /* run code here */ }
}

And we have Mammals.  They know how to run, but not fly nor chirp, nor
anything else much:

public class Mammals extend Creature
{
   public void run(int feet) { /* run code here */ }
}

We would like to keep track of the creatures that can fly, and of the ones
that can run.  So we build an interface representing these abilities:

public interface Airborne
{
   void fly(int feet);
}

public interface CanRun
{
   void run(int feet);
}

And then we make sure that the classes that we already have created
implement these interfaces.  Implementing the interfaces doesn't make them
have any abilities they didn't already have, it just allows us to put them
into useful categories (the OO purists are groaning here, but bear with me):

public class Bird implements Airborne
{
   public void fly(int feet) { /* fly code here */ }
   public void chirp() { /* chirping code here */ }
}

public class Bug implements Airborne, CanRun
{
   public void fly(int feet) { /* fly code here */ }
   public void run(int feet) { /* run code here */ }
}

public class Mammals implements CanRun
{
   public void run(int feet) { /* run code here */ }
}

Why the heck is this useful?  Well let's pretend you had the following
objects:

Bird bird1 = new Bird();
Bird bird2 = new Bird();
Bird bird3 = new Bird();
Bug bug1 = new Bug();
Bug bug2 = new Bug();
Mammal mammal1 = new Mammal();
Mammal mammal2 = new Mammal();
Mammal mammal3 = new Mammal();
Mammal mammal4 = new Mammal();
Mammal mammal5 = new Mammal();

You could then create an array of just the creatures that can fly:

Airborne[] flyingCreatures = { bird1, bird2, bird3, bug1, bug2 };

You would not be able to add any of the mammals:

// Error: mammal1 is not an Airborne object:
Airborne[] flyingCreatures = { bird1, bird2, bird3, bug1, bug2, mammal1 };

You could then also have a collection of the creatures that run.  Note, that
some of these also fly:

CanRun[] runningCreatures = {bug1, bug2, mammal1, mammal2, mammal3, mammal4,
mammal5}

...but of course, you would not be able to add any birds to this list.

All of this hoo-hah is an enforement of type-safety.  You now have a way of
specifying only things that fly, and only things that run.

For example, we could create a method that makes the given airborne create
fly a mile:

   public void flyAMile(Airborne flyingCreature)
   {
       flyingCreature.fly(5280);
   }

And we could then call this:

   flyAMile(bird2);

And specifically not this:

   flyAMile(mammal4);

I'm betting you have this part down cold already.  Do you?

Signature

Sometimes life just sucks and then you live.

Will - 17 Jul 2005 14:57 GMT
Thomas, I compiled and ran your code.
Indeed, an array of objects that all
implement the same interface does exclude
non implementer classes. I cast one to the
Interface it compiled, but it did not run.
Here is the code (based on yours):

public interface Airborne
{
   void fly(int feet);
}

public class Bird implements Airborne
{
   public void fly(int feet) {  }
   public void chirp() {  }
}

public class Bug implements Airborne
{
   public void fly(int feet) { }
   public void run(int feet) { }
}

public class Mammals
{
   public void run(int feet) { }
}

public class Tester
{

public static void main(String [] args)  {
Bird bird1 = new Bird();
Bug bug1 = new Bug();
Mammals mammals1 = new Mammals();

Airborne [] flyers = {bird1, bug1, (Airborne)mammals1};
    flyers[0].fly(2);
    flyers[1].fly(7);
    flyers[2].fly(9);
    }
}
Compiles OK but won't run (as expected
because mammals is not an Airborne)
OUTPUT:
java.lang.ClassCastException: Mammals
       at Tester.main(Tester.java:9)
Press any key to continue...

I see that that is useful in OO.
Below is a practical example of an interface
being used to compare objects. (Comparator)
At NO POINT is the Interface method called
from the code. But it is being called in
reality (its called from somewhere 5 times
- I have tested it)
This required Interface method is called:
-public int compareTo(some Params)-. What
or who is calling it 5 times?
Note, in my sphere of thinking it (the
interface method) is actually doing some
work. But I understood that Interface methods
have no implementation. Yet it compared
objects in a complicated way 5 times!

Here is the working code: (I tested it)

class Person implements Comparable {
 private String firstName;
 private String lastName;
 private int age;

 public String getLastName() {
   return lastName;
 }

 public void setLastName(String lastName) {
   this.lastName = lastName;
 }

 public int getAge() {
   return age;
 }

 public void setAge(int age) {
   this.age = age;
 }

public int compareTo(Object anotherPerson) throws ClassCastException {
if (!(anotherPerson instanceof Person))
throw new ClassCastException("A Person object expected.");
int anotherPersonAge = ((Person) anotherPerson).getAge();
return this.age - anotherPersonAge;
 }
}

import java.util.Arrays;

public class Testing {

 public static void main(String[] args) {
   Person[] persons = new Person[4];
   persons[0] = new Person();
   persons[0].setLastName("Goodyear");
   persons[0].setAge(56);
   persons[1] = new Person();
   persons[1].setLastName("Clark");
   persons[1].setAge(8);
   persons[2] = new Person();
   persons[2].setLastName("Graff");
   persons[2].setAge(16);
   persons[3] = new Person();
   persons[3].setLastName("Goodyear");
   persons[3].setAge(69);

   System.out.println("Natural Order");

   for (int i=0; i<4; i++) {
     Person person = persons[i];
     String lastName = person.getLastName();
     int age = person.getAge();
     System.out.println(lastName +". Age:" + age);
   }

   Arrays.sort(persons);

   System.out.println();
   System.out.println("Sorted by age");

   for (int i=0; i<4; i++) {
     Person person = persons[i];
     String lastName = person.getLastName();
     int age = person.getAge();
     System.out.println(lastName +". Age:" + age);
   }
 }
}
Thomas G. Marshall - 17 Jul 2005 17:26 GMT
Will coughed up:
> Thomas, I compiled and ran your code.
> Indeed, an array of objects that all
> implement the same interface does exclude
> non implementer classes. I cast one to the
> Interface it compiled, but it did not run.

...[rip]...

> Airborne [] flyers = {bird1, bug1, (Airborne)mammals1};
> flyers[0].fly(2);
[quoted text clipped - 4 lines]
> Compiles OK but won't run (as expected
> because mammals is not an Airborne)

Yes.  Well, it compiles ok only because the java compiler does not try
particularly hard to see if the mammals reference is of a compatible type to
Airborne.  It takes the cast and assumes that you know what you're doing.
I've often thought that in *simple cases* that the compiler should at least
issue a warning with words to the effect of:

       "you're attempting a cast to something that does not
       seem compatible.  mammals1 seems to be of type
       bla bla bla are"

If you attempt a cast to something else entirely

       Airborne [] flyers = {bird1, bug1, (String)mammals1};

The compiler will punt with an "incompatible type" error message (it'll
compare String to Airborne).

> OUTPUT:
> java.lang.ClassCastException: Mammals
[quoted text clipped - 8 lines]
> reality (its called from somewhere 5 times
> - I have tested it)

It is being called by Arrays.sort().  Here is what the documentation for
Arrays.sort() says:

   public static void sort(Object[] a)
   Sorts the specified array of objects into ascending
   order, according to the natural ordering of its
   elements. All elements in the array must implement
   the Comparable interface.  [...]

Each element must implement that Comparable interface, so that Arrays.sort()
is guaranteed to have a compareTo() method to call.  Arrays.sort() uses the
compareTo() method of each of the objects in the array to determine what
order to place them in.

If this still confuses you, or if you need a rewording of this, let me know
asap.

...[rip]...

Signature

Having a dog that is a purebred does not qualify it for breeding.  Dogs
need to have several generations of clearances for various illnesses
before being bred.  If you are breeding dogs without taking care as to
the genetic quality of the dog (again, being purebred is *not* enough),
you are what is known as a "backyard breeder" and are part of the
problem.  Most of the congenital problems of present day dogs are
traceable directly to backyard breeding.  Spay or neuter your pet
responsibly, and don't just think that you're somehow the exception and
can breed a dog without taking the care described.

Patricia Shanahan - 17 Jul 2005 17:58 GMT
> Will coughed up:
>
[quoted text clipped - 24 lines]
>         seem compatible.  mammals1 seems to be of type
>         bla bla bla are"

I don't think this is an appropriate case for a warning, because I
believe it should be possible to remove all warnings from a runtime
correct program by appropriate casting etc.

Consider:

class Bat extends Mammals implements Airborne{
...
}

Patricia
Thomas G. Marshall - 17 Jul 2005 22:39 GMT
Patricia Shanahan coughed up:
>> Will coughed up:
>>
[quoted text clipped - 35 lines]
>
> Patricia

I see, and agree, thanks.  Muse with me the following case (slightly to the
side):

   Object mumble = new ArrayList();
   String str = (String)mumble;

It is very hard for a compiler to determine what to do in this case, because
a carefully timed thread could plant a String into mumble between line 1 and
line 2, allowing line 2 to execute without error.  The reason that this is
difficult for the compiler is because Object is a superclass to String.

But consider this case:

   String mumble = "hello";
   List list = (List)mumble;

There is *no situation* where mumble can /ever/ become part of the List
hierarchy.  And in fact the compiler is just fine with kicking out an error:

       String str = "hello";
       List list = (List)str;

compiler error:
javac 1.5.0-beta2
Cast.java:41: inconvertible types
found   : java.lang.String
required: java.util.List
       List list = (List)mumble;
                         ^
1 error

...as it should because String is final, and therefore, as in your example,
it can never be extended into something that implements List or a List
subinterface.

And as you point out

   interface Airborne
   {
       void fly(int feet);
   }

   class Mammal
   {
       public void run(int feet) { }
   }

   class Bat extends Mammal implements Airborne
   {
   }

   Mammal mammal = new Mammal();
   Airborne flyers1 = (Airborne)mammal;

mammal might be assigned a Bat elsewhere, "in time".

Thanks Patricia, for making this clear.

Signature

Having a dog that is a purebred does not qualify it for breeding.  Dogs
need to have several generations of clearances for various illnesses
before being bred.  If you are breeding dogs without taking care as to
the genetic quality of the dog (again, being purebred is *not* enough),
you are what is known as a "backyard breeder" and are part of the
problem.  Most of the congenital problems of present day dogs are
traceable directly to backyard breeding.  Spay or neuter your pet
responsibly, and don't just think that you're somehow the exception and
can breed a dog without taking the care described.

Patricia Shanahan - 17 Jul 2005 23:11 GMT
> Patricia Shanahan coughed up:
>
[quoted text clipped - 48 lines]
> line 2, allowing line 2 to execute without error.  The reason that this is
> difficult for the compiler is because Object is a superclass to String.

In theory, at least in some situations, the compiler could apply data
flow analysis to bound the classes of objects referenced by variables,
beyond the limitations imposed by the variable types. In your example,
there is no asynchronous access to local variables, so the compiler
could know that the cast must fail at run time.

However, the JLS rules for casting conversion are expressed only in
terms of declared, compile-time types. The rules make sense in terms of
the question "Could there exist an object would make this cast valid?"
but with reference expression treated as being capable of referencing
any object whose class is appropriate for its type. Object is a
superclass of String, so mumble's type allows it to reference a String.

> But consider this case:
>
[quoted text clipped - 3 lines]
> There is *no situation* where mumble can /ever/ become part of the List
> hierarchy.

The key fact is that it is possible to deduce that mumble does not
reference a List by looking only at the types involved. The finality of
String ensures that mumble must reference an actual String, not an
object of a hypothetical, List-implementing subclass of String.

The full and gory rules, including distinctions between final and
non-final classes, are in the JLS at
http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#20232

Patricia
Will - 17 Jul 2005 19:50 GMT
Yes Thomas, I looked in the class Array for the method sort(object [])
and it was there and needed a Comparable object. It then started
calling
my implementation of compareTo() and doing a sort() algorithm. So I
begin
to see that interfaces do something by using classes such as Array,
Thread,
ActionListener which demand Interface objects and then appear to call
our
implementations with something useful and similar in functionality to
MI.
I admit that the dog breeding example left me completely bemused. I
simply cannot relate it to programs unless what inherits and what
Interfaces is
spelt out. I lose the thread of the argument. But the Arrays sort() I
understood well. I think I'll get somewhere now.
If you get time can you comment on Patricas observation as I did not
understand her point, but it could be salient.
Thomas G. Marshall - 17 Jul 2005 22:44 GMT
Will coughed up:
> Yes Thomas, I looked in the class Array for the method sort(object [])
> and it was there and needed a Comparable object. It then started
[quoted text clipped - 14 lines]
> If you get time can you comment on Patricas observation as I did not
> understand her point, but it could be salient.

I commented on it, so hopefully it'll make sense.

The dog breeding (lol) comment is part of a rotating signature.  It has
nothing whatsoever to do with java nor OO.  It has to do with people
breeding dogs who don't understand what the heck they are doing.

So don't short out any synapse trying to adapt it to java.  Oye!  That
must've been some mental gymnastics you were going through!!!!!

Signature

Having a dog that is a purebred does not qualify it for breeding.  Dogs
need to have several generations of clearances for various illnesses
before being bred.  If you are breeding dogs without taking care as to
the genetic quality of the dog (again, being purebred is *not* enough),
you are what is known as a "backyard breeder" and are part of the
problem.  Most of the congenital problems of present day dogs are
traceable directly to backyard breeding.  Spay or neuter your pet
responsibly, and don't just think that you're somehow the exception and
can breed a dog without taking the care described.

Will - 18 Jul 2005 15:56 GMT
Yes, Thomas, I thought the dog breeder was an
Interface that only allowed certain generations
of dogs to breed!! (& inherited class illnesses
etc).
I must have Asbergers.
billreyn@gmail.com - 18 Jul 2005 22:18 GMT
Yes Thomas, I thought that we were using
interfaces to limit dog types and there was
some sort of 'inherited' illness class problem
with the dogs. I must have Asbergers. lol
Will - 16 Jul 2005 12:32 GMT
Hello Damec
I ran your code and saw that passing an Interface
type object indeed ran the correct methods, but
these methods were composed from instantation of
objects. So I removed all the interfaces and
ran  the same code with thae same result. Here is
the code:

public interface Foo { // not used
   public void saySomething();

}

public interface Bar { // not used
   public void saySomethingElse();

}

public class A  { // removed implements

   public void saySomething() {
   System.out.println("A says something");
   }

}

public class B  { // removed implements

public void saySomethingElse() {
   System.out.println("B says something else");
   }
}
public class C

  { // removed implements

   private A a_ = new A();
   private B b_ = new B();
   public void saySomething() {
       this.a_.saySomething();
   }
   public void saySomethingElse() {
       this.b_.saySomethingElse();
   }

}

public class Main {

// now f is a C
public static void doSomethingWithAClassThatIsAFo­o(C f) {
       f.saySomething();
   }
// now b is a C
 public static void doSomethingWithAClassThatIsABa­r(C

b) {
       b.saySomethingElse();
   }
public static void main(String[] args) {
      C test = new C();
       doSomethingWithAClassThatIsABa­r(test);
       doSomethingWithAClassThatIsAFo­o(test

);
   }

}

OUTPUT:
B says something else
A says something
Press any key to continue...

I must be the only one that does not
understand this, I can see that a
foo Interface object does the trick,
but it is still using good old
instantiation of classes A & B to get
at the method implementations in A & C
& I can do this anyway (MI, Interface or
not). I just do an instantation & method
call. The Interface seems to do nothing
to help except we write more code. And
how come real interfaces actually do stuff
like compare objects and run threads. Is
it method call backs and messaging?
Maybe its something so simple that I just
cant see it. I have tried & tried to grasp it.
Wibble - 16 Jul 2005 14:32 GMT
> Hello Damec
> I ran your code and saw that passing an Interface
[quoted text clipped - 85 lines]
> Maybe its something so simple that I just
> cant see it. I have tried & tried to grasp it.

You are confused.  Real interfaces never do anything, ever at runtime.

They allow a gadget like thread to call passedInRunnable.run() because
they defined an interface and require thier callbacks to look a certain way.

Interfaces are always backed by implementations at runtime, including
for Runnable, Comparable, Comparator, Serializable, Cloneable etc.

(dont go on about instanceof, constants, reflection or other
obfuscations please, it wont help this guy)
Dan McLeran - 16 Jul 2005 16:19 GMT
Will,

You have changed the example in a fundamental way by changing the
method signatures from something that expects a Foo or Bar to something
that expects class C. This completely defeats the original purpose,
which was to mimic multiple inheritance. If you want class C to inherit
the functionality of both A & B, you cannot do this directly in Java:

class C extends A, B // will not compile

What you can do is implement any number of interfaces you like. So, if
you create a class to implement the Foo interface (class A) and create
another class to implement the Bar interface (class B) and then create
a class that implements both Foo and Bar (class C) then you can provide
class C with instances of classes A & B and forward all method calls
from interfaces Foo and Bar to those class members. This provides the
'look and feel' of multiple inheritance. Of course, it isn't real
multiple inheritance because you could not pass instances of C to a
method that expects an instance of A, which you would be able to do if
'real' multiple inheritance was used.

Maybe a different example will help clear things up. Let's use a
variation of the Animal hierarchy:

The Animal class is the parent class for all animals.The Employee class
is the parent class for all employess of a fire station. The Secretary
class hands out the payment for all employees of the fire station. The
Secretary only hands out payments to classes that implement the
IEmployee interface. The WorkingDogHolder class needs to implement all
Animal behaviour and Employee behaviour, because these dogs can be
employees. Since most Dogs are not employees, we'll create a Dog class
that extends Animal via single inheritance. To provide the look and
feel of multiple inheritance for a Dog that is an Employee, we'll
create a WorkingDogHolder class that needs to provide behaviour for
both Dog and Employee. We'll do this by implementing both IAnimal and
IEmployee and holding instances to an Dog class and Employee class.
We'll also provide a Groomer class that will groom all animals, but not
Employees.

public interface IAnimal {
   public void eat();
   public void receiveGrooming();
}

public interface IEmployee {
   public void receivePayment();
}

public class Animal implements IAnimal {

   /* (non-Javadoc)
    * @see IAnimal#eat()
    */
   public void eat() {
       System.out.println("Animals love to eat!");
   }

   public void receiveGrooming() {
       System.out.println("Animals love a good grooming");
   }
}

public class Dog extends Animal {
   public void eat() {
       System.out.println("Dogs love to eat!");
   }

   public void receiveGrooming() {
       System.out.println("Dogs love a good grooming");
   }
}

public class Employee implements IEmployee {

   /* (non-Javadoc)
    * @see IEmployee#receivePayment()
    */
   public void receivePayment() {
       System.out.println("I love payday!");
   }
}

public class WorkingDogHolder implements IAnimal, IEmployee {
   private final Employee employee_ = new Employee();
   private final Dog dog_ = new Dog();

   public void receivePayment() {
       this.employee_.receivePayment();
       this.eat();
   }

   public void eat() {
       this.dog_.eat();
   }

   public void receiveGrooming() {
       this.dog_.receiveGrooming();
   }
}

public class Groomer {
   public void groomAnimal(final IAnimal animal) {
       animal.receiveGrooming();
   }
}

public class Secretary{
   public void providePayment(final IEmployee employee) {
       employee.receivePayment();
   }
}

public class Main {

   public static void main(String[] args) {
       Employee humanEmployee = new Employee();
       WorkingDogHolder workingDog = new WorkingDogHolder();
       Dog normalDog = new Dog();
       Secretary secretary = new Secretary();
       Groomer groomer = new Groomer();

       secretary.providePayment(humanEmployee);
       secretary.providePayment(workingDog);
       //secretary.providePayment(normalDog);    //won't compile because
                                               //a normal dog doesn't
                           //get paid
       groomer.groomAnimal(normalDog);
       groomer.groomAnimal(workingDog);
       //groomer.groomAnimal(humanEmployee);    //won't compile because
                                               //a human can't
                           //be groomed in this example
   }
}
Raymond DeCampo - 15 Jul 2005 16:02 GMT
> You cannot inherit from more than one super class in Java, but
> according to all the texts 'Interfaces allow you to 'inherit' from
[quoted text clipped - 3 lines]
> as I have read too much about them over and over.
> Any kind clever person can explain in words on one syllable?

I will try to explain, but it will be impossible without using
multi-syllabic words, e.g. interface.

Simply put, the type of "inheritance" that interfaces supply do not
allow you to inherit any implementation.  Interfaces were not designed
to do that.  So when you implement an interface, you must supply all of
the implementation in the implementing class (or one of its superclasses).

HTH,
Ray

Signature

XML is the programmer's duct tape.

Thomas G. Marshall - 15 Jul 2005 16:28 GMT
Will coughed up:
> You cannot inherit from more than one super class in Java, but
> according to all the texts 'Interfaces allow you to 'inherit' from
[quoted text clipped - 3 lines]
> 'contracts' as I have read too much about them over and over.
> Any kind clever person can explain in words on one syllable?

There is no way to /directly/ MI the implementations you are looking for
using interfaces.

When I was contracted to teach java I was very careful to avoid the common
read/heard words:

   "java does not have MI, but it has interfaces instead"

Because MI and interfaces do not 1:1 equate.

There are many ways of using interfaces, and they are too much to discuss
right now, but they just don't deliver MI (as such) to you.  (as they should
not---I believe MI to be a way of establishing hard to discover bugs).

"danmcleran"'s post is the most appropos.

Signature

http://www.allexperts.com is a nifty way to get an answer to just about
/anything/.

timjowers@gmail.com - 15 Jul 2005 19:28 GMT
 Yeah, Java interfaces are a punt WRT MI (multiple implements). But
probably it's a bug to extend two interfaces which have an identical
method sig. Does the javac error message on doing this?

TimJowers
danmcleran@yahoo.com - 15 Jul 2005 19:51 GMT
Why is it a bug? I'm sure that there are many interfaces with the
method signature void methodName(). Why would it be illegal to extend 2
interfaces that contain methods with the same signature? The Java
compiler does not complain and the code compiles and runs fine under
JDK 1.4.2.
Lasse Reichstein Nielsen - 15 Jul 2005 20:19 GMT
> Why is it a bug?

Not a bug, but probably unintentional.

> I'm sure that there are many interfaces with the method signature
> void methodName(). Why would it be illegal to extend 2 interfaces
> that contain methods with the same signature?

Because the *meaning* of the two methods in the two interfaces are
probably different. Like the hypothetical interfaces "Exception" and
"Javelin", which both have a method "void throw()".

If both interfaces have javadoc for the method, which one will
the implementation inherit?

> The Java compiler does not complain and the code compiles and runs
> fine under JDK 1.4.2.

True. Personally, I would prefer at least a warning.

/L
Signature

Lasse Reichstein Nielsen  -  lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
 'Faith without judgement merely degrades the spirit divine.'

Stefan Ram - 15 Jul 2005 20:28 GMT
>Because the *meaning* of the two methods in the two interfaces are
>probably different. Like the hypothetical interfaces "Exception" and
>"Javelin", which both have a method "void throw()".

 One would have to use another level of indirection:

Instance instance = new Instance();
ExceptionInterface exceptionInterface = instance.getExceptionInterface();
JavalinInterface   javelinInterface   = instance.getJavelinInterface();
exceptionInterface.throw();
javelinInterface.throw();

 Where the getters then might actually create new objects,
 delegation the throw calls to the instance.
Eric Sosman - 15 Jul 2005 21:00 GMT
>   Yeah, Java interfaces are a punt WRT MI (multiple implements). But
> probably it's a bug to extend two interfaces which have an identical
> method sig. Does the javac error message on doing this?

   No.  (You *could* have tried it for yourself ...)

   It's an ugly spot in the language, a place where names
can "escape" their packages and collide with each other.
Them's the breaks.

Signature

Eric.Sosman@sun.com

Tim Tyler - 27 Jul 2005 10:10 GMT
timjowers@gmail.com wrote or quoted:

>   Yeah, Java interfaces are a punt WRT MI (multiple implements). But
> probably it's a bug to extend two interfaces which have an identical
> method sig. Does the javac error message on doing this?

No.
Signature

__________
|im |yler  http://timtyler.org/  tim@tt1lock.org  Remove lock to reply.

Andrew McDonagh - 15 Jul 2005 23:18 GMT
> You cannot inherit from more than one super class in Java, but
> according to all the texts 'Interfaces allow you to 'inherit' from
[quoted text clipped - 3 lines]
> as I have read too much about them over and over.
> Any kind clever person can explain in words on one syllable?

Java does not support multiple *implementation* inheritance - as in
the C++ does.

It does support multiple interface inheritance.

Interfaces are not purely about the methods that must be implemented.
They are first and foremost a typing specification.

class abstract Foo {
  public abstract void bark();
}

is almost the same as:

interface Foo {
   void bark();
}

The difference is that interfaces are more tightly constrained as to
what we can put in them and how other classes can implement them.

A derived class of the abstract Foo Class would not be allowed to derive
from any other class, because Java does not support Multiple
*implementation* inheritance.

However, any class can support multiple  *interface* implementation.

Interfaces can not have any implementations, only method signatures and
constants. Where as abstract classes CAN have some implemented methods.

Andrew
Tim Tyler - 27 Jul 2005 10:22 GMT
Will <billreyn@hotmail.com> wrote or quoted:

> You cannot inherit from more than one super class in Java, but
> according to all the texts 'Interfaces allow you to 'inherit' from
[quoted text clipped - 3 lines]
> earth does an Interface allow you to use methods from other
> classes -  a method name is just a name.

A name - and some parameter types - and some constants.

Note that you can do this:

interface Foo {
MyType constant1 = new MyType() {
 void whatever() {...}
 void you() {...}
 void like() {...}
 void here() {...}
}
}

interface Bar {
MyType constant2 = new MyType() {
 void more() {...}
 void stuff() {...}
 void available() {...}
 void here() {...}
}
}

That effectively allows you to include code from all over the place by
implementing multiple interfaces.
Signature

__________
|im |yler  http://timtyler.org/  tim@tt1lock.org  Remove lock to reply.

Thomas G. Marshall - 27 Jul 2005 13:59 GMT
Tim Tyler coughed up:
> Will <billreyn@hotmail.com> wrote or quoted:
>
[quoted text clipped - 32 lines]
>> im |yler  http://timtyler.org/  tim@tt1lock.org  Remove lock to
>> reply.

No, this talks past what he is confused about.  I believe his complaint is
that when you "include code from all over the place", you tend to have to
duplicate it.  This is true, or at least to the extent that you must find a
way around it: interfaces do not let you inherit implementations, as stated,
and as you obviously know.

Signature

Forgetthesong,I'dratherhavethefrontallobotomy...

Tim Tyler - 27 Jul 2005 14:47 GMT
Thomas G. Marshall <tgm2tothe10thpower@replacetextwithnumber.hotmail.com> wrote or quoted:
> Tim Tyler coughed up:

> > Note that you can do this:
> >
[quoted text clipped - 24 lines]
> way around it: interfaces do not let you inherit implementations, as stated,
> and as you obviously know.

It's not quite as bad as all that:  You can include an interface
which contains a constant instance of an object - intended to do
all the work which is to be inherited - and then implement the
interface using a bunch of one-line delegates - that call the
corresponding methods of the included object.

That way you do effectively multiply-inherit the guts of the
implementation - though the programmer has to fill in some
associated bubble-gum code to make sure it gets called.

I think it's known as the interface-delegation pattern, or some
such - there's a description in:

http://www.mcs.vuw.ac.nz/comp/Publications/CS-TR-98-1.abs.html

The pattern effectively lets you include logic - but not state.

IMO, the biggest problem with multiple inheritance is how to
resolve name clashes:

class DefenseStation extends Missile, Employee {
  void fire() {
    // fire missile - or fire employee?!?
  }
}

Java offers programmers no assistance with that problem.
Signature

__________
|im |yler  http://timtyler.org/  tim@tt1lock.org  Remove lock to reply.

Thomas G. Marshall - 27 Jul 2005 19:38 GMT
Tim Tyler coughed up:
> Thomas G. Marshall
> <tgm2tothe10thpower@replacetextwithnumber.hotmail.com> wrote or
[quoted text clipped - 57 lines]
>
> Java offers programmers no assistance with that problem.

I thought that way early on, FWIW.  I've since changed my mind to believing
that it is infact not a problem at all.  Interfaces establish contracts.
The only requirement for a java interface contract is that the method be
implemented *somewhere* in the class or upstream (let's keep the nitpicking
out of it for now :) ) with the signature and return type.

For example, consider this *differing* notion:

   interface MethodContract { void method(); }

   class A { public void method() {...} }

   class B extends A, implements MethodContract{...}

As it turns out, the contract MC is already satisfied by the superclass.
There is no "protection" for this either.  Mostly, IMO, because it does not
need it---it is not a problem either.

Signature

If I can ever figure out how, I hope that someday I'll
succeed in my lifetime goal of creating a signature
that ends with the word "blarphoogy".

Tim Tyler - 27 Jul 2005 20:08 GMT
Thomas G. Marshall <tgm2tothe10thpower@replacetextwithnumber.hotmail.com> wrote or quoted:
> Tim Tyler coughed up:

> > IMO, the biggest problem with multiple inheritance is how to
> > resolve name clashes:
[quoted text clipped - 24 lines]
> There is no "protection" for this either.  Mostly, IMO, because it does not
> need it---it is not a problem either.

If you implement two different interfaces with the same method signature
in them in Java, the methods simply clash.

I wouldn't describe that as being "not a problem at all".
Signature

__________
|im |yler  http://timtyler.org/  tim@tt1lock.org  Remove lock to reply.

Thomas G. Marshall - 29 Jul 2005 00:14 GMT
Tim Tyler coughed up:
> Thomas G. Marshall
> <tgm2tothe10thpower@replacetextwithnumber.hotmail.com> wrote or
[quoted text clipped - 36 lines]
>
> I wouldn't describe that as being "not a problem at all".

You've made a good point.  If you have two disparate interfaces whose
signatures collide, then yes Houston, you have a problem.

I was more speaking to /overlapping/ interfaces, where a contract is doubly
specified, which I see as a non issue.  You're absolutely right.

Signature

Framsticks.  3D Artificial Life evolution.  You can see the creatures
that evolve and how they interact, hunt, swim, etc. (Unaffiliated with
me). http://www.frams.alife.pl/



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.