• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

puzzled by this question

 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One page 628 of the Java 5 study guide:

interface Hungry<E> { void munch(E x); }
interface Carnivore<E extends Animal> extends Hungry<E> {}
interface Herbivore<E extends Plant> extends Hungry<E> {}
abstract class Plant {}
class Grass extends Plant {}
abstract class Animal {}
class Sheep extends Animal implements Herbivore<Sheep> {
public void munch(Sheep x) {}
}
class Wolf extends Animal implements Carnivore<Sheep> {
public void much(Sheep x) {}
}

Why wouldn't the following change work?
D. Change the Sheep class to
class Sheep extends Plant implements Carnivore<Wolf> {
public void munch(Wolf x) {}
}

Thanks.
 
Ranch Hand
Posts: 232
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Question:

Which of the following changes (taken separately) would allow this code to compile?
(Choose all that apply.)
A. Change the Carnivore interface to
interface Carnivore<E extends Plant> extends Hungry<E> {}
B. Change the Herbivore interface to
interface Herbivore<E extends Animal> extends Hungry<E> {}
C. Change the Sheep class to
class Sheep extends Animal implements Herbivore<Plant> {
public void munch(Grass x) {}
}
D. Change the Sheep class to
class Sheep extends Plant implements Carnivore<Wolf> {
public void munch(Wolf x) {}
}
E. Change the Wolf class to
class Wolf extends Animal implements Herbivore<Grass> {
public void munch(Grass x) {}
}
F. No changes are necessary.



Answer:

B is correct. The problem with the original code is that Sheep tries to implement
Herbivore<Sheep> and Herbivore declares that its type parameter E can be any type that
extends Plant. Since a Sheep is not a Plant, Herbivore<Sheep> makes no sense�
the type Sheep is outside the allowed range of Herbivore's parameter E. Only solutions that
either alter the definition of a Sheep or alter the definition of Herbivore will be able to fix
this. So A, E, and F are eliminated. B works, changing the definition of an Herbivore to
allow it to eat Sheep solves the problem. C doesn't work because an Herbivore<Plant>
must have a munch(Plant) method, not munch(Grass). And D doesn't work, because
in D we made Sheep extend Plant, now the Wolf class breaks because its munch(Sheep)
method no longer fulfills the contract of Carnivore. (Objective 6.4)


So, when you make sheep correct you brake wolf (since wolf is eating Sheep, and agreement says: <E extends Animal> NOT <e extends Plant> )
[ October 24, 2007: Message edited by: Jari Timonen ]
 
Ranch Hand
Posts: 186
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
May i ask why C cant make the answer.

the answer explained :
"C doesnt work because an Herbivore<Plant> must have a munch(Plant) method, not munch Grass."

ok, we sub Plant into the E placeholder in the code.
[code]
interface Hungry<Plant> { void munch(Plant x); }-- change made, line 1, my doubt here
interface Carnivore<E extends Animal> extends Hungry<E> {}
interface Herbivore<Plant extends Plant> extends Hungry<E> {}-- change made
abstract class Plant {}
class Grass extends Plant {}
abstract class Animal {}
class Sheep extends Animal implements Herbivore<Plant> {-- change made
public void munch(Grass x) {} -- change made
}
class Wolf extends Animal implements Carnivore<Sheep> {
public void much(Sheep x) {}
}

i could be wrong. According the book, subtypes can take effect in generics, so Grass is a subclass, or an instanceof of Plant, so at line 1 should be fine. i.e.
in Hungry interface
public void munch(Plant x) {}
in sheep class, which implements Hungry
public void munch(Grass x) {}


or this is illegal as an OO rule?
 
Ranch Hand
Posts: 513
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by adam Lui:
i could be wrong. According the book, subtypes can take effect in generics, so Grass is a subclass, or an instanceof of Plant, so at line 1 should be fine. i.e.
in Hungry interface
public void munch(Plant x) {}
in sheep class, which implements Hungry
public void munch(Grass x) {}


Hi Adam,

You should think of an interface method as basically an abstract method that you must override in a concrete class. To override a method, you must provide an implementation that has exactly the same signature (i.e. same method name and parameter types). If you change the parameter types, you're overloading the method, not overriding it, so that's not enough to fulfill the contract of the interface.

While it's true that you can change the method's return type to a covariant type, this doesn't apply to the parameter types.
 
adam Lui
Ranch Hand
Posts: 186
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
THANKS Kelvin
 
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The explanation of why C doesn't work was very helpful. Thanks.

I'm still unclear on how D breaks the contract of Carnivore. Something isn't clicking in to place.
 
Karen Marie
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Nevermind. It clicked.

Sheep extends Plant means that now Sheep IS-A Plant. Carnivore<E extends Animal> means the generic type of Carnivore must be Animal or something that extends Animal.

So while D compiles fine in the originally broken line:
class Sheep extends Plant implements Carnivore<Wolf>{
public void munch(Wolf x){ }
}

...it now breaks the line that previously compiled...:
class Wolf extends Animals implements Carnivore<Sheep>{
public void munch(Sheep x){ }
}

...since Sheep no longer extends Animal.
 
There's a city wid manhunt for this tiny ad:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic