Я предлагаю:
- использовать только интерфейсы для всей иерархии.
- отделить поведения и инкапсулировать их в отдельных классах.
- использовать композицию вместо наследования, то есть private SomeBehavior someBehavior;для каждого конкретного животного, которое нуждается в этом.
Это улучшит ваш дизайн и решит проблему.
i.e.
public interface Mammals {
}
public interface Animal extends Mammals {
}
public interface Dog extends Animal {
}
and
public class TakeADump {
public void dump() {
}
}
public class TakeAPee {
public void pee() {
}
}
, а затем
public class Sheperd implements Dog {
private TakeADump dumpService;
private TakeApee peeService;
}
И теперь ваша собака может s ... и p ...:)
Также добавить
public class F... {
public void f...(<Animal> animal) {
// ... check it's an instance of the same or compatible animal or throw UnsupportedOperationException() if it's incompatible
}
}
: D
Конечно, имеет смысл создатьабстрактное животное.
т.е.
public class AbstractAnimal {
private TakeADump dumpService;
private TakeApee peeService;
private F... f...Service;
}
затем
public abstract class AbstractDog extends AbstractAnimal implements Dog {
}
и
public class Sheperd extends AbstractDog {
public void lookAfterSheep() {
Sheep sheep = SheepLocator.findNearest();
// pee on a sheep
peeService.pee(sheep);
// dump on a sheep
dumpService.dump(sheep);
// f... a sheep
f...Service.mount(sheep);
}
}
Таким образом, ваша ошибка заключается в использовании слишком большого количества абстрактного, когда вы можете использовать интерфейсы.