How can I get these classes to inherit these traits?

时间:2016-07-11 22:25:44

标签: java inheritance polymorphism

My problem stipulates the following, dealing with birds:

  1. Birds can fly.
  2. Ducks fly but also swim.
  3. Penguins do not fly.
  4. Penguins deep dive, unlike ducks.
  5. Only parrots can talk.

Here is my code:

import java.util.*;
public class Code
{
  public static void main(String[] args) 
  {
    Bird[] birds = new Bird[3]; 
    birds[0] = new Duck(true, false, false, false); 
    birds[1] = new Penguin(false, true, false, true); 
    birds[2] = new Parrot(true, false, true, false); 
  }
}

abstract class Bird 
{ 
  abstract boolean flight();
  abstract boolean deepdive();
  abstract boolean talk();
  abstract boolean swim();

  Bird (boolean flight, boolean deepdive, boolean talk, boolean swim)
  {
    this.flight = flight;
    this.deepdive = deepdive;
    this.talk = talk;
    this.swim = swim;
  }

}

abstract class Duck extends Bird
{
  public Duck(boolean flight, boolean deepdive, boolean talk, boolean swim)
  {
    super(flight, deepdive, talk, swim);
  }
  abstract public boolean flight();
  abstract public boolean deepdive();
  abstract public boolean talk();
  abstract public boolean swim();
}

abstract class Penguin extends Bird
{
  public Penguin(boolean flight, boolean deepdive, boolean talk, boolean swim)
  {
    super(flight, deepdive, talk, swim);
  }
  abstract public boolean flight();
  abstract public boolean deepdive();
  abstract public boolean talk();
  abstract public boolean swim();
}

abstract class Parrot extends Bird
{
  public Parrot(boolean flight, boolean deepdive, boolean talk, boolean swim)
  {
    super(flight, deepdive, talk, swim);
  } 
  abstract public boolean flight();
  abstract public boolean deepdive();
  abstract public boolean talk();
  abstract public boolean swim();
}

My idea was to have each activity as a true or false field, and then output from each animal saying what he can and cannot do, via a loop. However, whenever I try to get it to run, it gives me: "Void methods cannot return a value" and "This method requires a body instead of a semicolon." How can I get this to work?

EDIT: I've implemented some of what people said to do below, but I still get "cannot instantiate the type ..." and "...cannot be resolved or is not a field"

2 个答案:

答案 0 :(得分:2)

Lets focus in the model first.

The best way to represent this model in java is with concrete separated classes and interfaces.

class Bird implements Flyer
class Duck implements Flyer, Swimmer
class Penguin implements Swimmer, DeepDiver
class Parrot implements Flyer, Talker

Observe that Liskov Substitution Principle does not allow to remove behaviour from a superclass in a subclass. That is why you can not say that Bird is a Flyer, Penguin is a Bird but Penguin is not a Flyer. In other words other Bird users would expect the Flyer behaviour and that expectation would fail for Penguin, in this case inheritance is not the correct approach.

Now talking about implementation.

Java has no multiple inheritance or mix-in but in java 8 you can have a default method implementation in interfaces.

Hint: avoid using instanceof, use polymorphism instead.

答案 1 :(得分:0)

Problem 1: The compiler says that "void methods cannot return a value" is because you are returning the first Bird instance in your birds array in your main method, which is declared void.

To fix this, simply remove the for loop in your main method.

Problem 2: The compiler says that "This method requires a body instead of a semicolon" because methods without a body in an abstract class need to be declared abstract, like so:
abstract boolean flight();

To fix this, declare all the methods without a body in your Bird class abstract.

Problem 3: The compiler says that "you cannot instantiate the type" because the type you are trying to instantiate is an abstract class. The root of this problem is that Duck, Penguin, and Parrot are abstract classes when they don't need to be. The child classes of Bird should override the methods in the Bird class, that is why you declared the methods in the Bird class abstract.

To fix this, remove the abstract modifier on all of the methods in the Duck, Penguin, and Parrot classes and add a body to those methods. It is also conventional to add the @Override annotation on the line before any overridden method.

Problem 4: The compiler says that "XXX cannot be resolved or is not a field" means that you have not declared the fields flight, deepdive, talk, and swim.

To fix this, declare those fields in the Bird class (Example: private boolean XXX;).

However, this will give you an unused warning because in the code these fields will only have values and those values will never be used. To fix this you can remove the fields and the references to them entirely, make getters and setters for them, or any other method that would use them, or add @SuppressWarnings("unused") the line before the Bird class declaration (Not recommended).

Further reading:

Note: This should only be a temporary solution, as the answer @JonasFagundes suggested is simply a better way to tackle this problem as a whole.