Work around the need to override abstract methods in Java? - java

I've been working on an assignment that involves an abstract class that represents a generic animal, with subclasses for cat, dog, reptile, etc. The superclass has abstract methods that aren't actually used by each subclass. For example, there are accessors and mutators for breed and gender that are used by dog and cat but not the reptile class. I personally think this is an odd setup, but it's what is required by the assignment.
At first I tried leaving out the abstract methods not used in a particular subclass, but I quickly found out that leads to an error, due to abstract methods not being overridden. All I had to do to fix that was put in the appropriate methods...
public class Reptile extends Animal
...
public void setBreed(String newBreed){}
public String getBreed(){return null;}
...though it seems to be a bit of a waste seeing as they aren't used. It's not a huge issue, but it made me curious as to whether or not there is an alternative to having to override unused abstract methods in a given subclass. Barring that, is there any convention for what to do when you need to override an abstract method but won't actually be using the method at all?

You have two solutions here.
You can have multiple levels of abstract classes. In other words (these are shell classes and functions...i.e. no code):
public abstract class Animal{
public abstract void fooMethod();
}
public abstract class Pet extends Animal{
public abstract void breed();
public abstract void gender();
}
public class Reptile extends Animal{
public void fooMethod(){}
}
public class Cat extends Pet{ //do the same for Dog
public void fooMethod(){}
public void breed(){}
public void gender(){}
}
This way, Reptile still extends Animal, but you know Reptile doesn't have a breed or gender function, so you don't have to do anything for it. Similarly, Cat and Dog also extend Animal, but now they have breed and gender they must override as well.
Your other solution is to do something like this (the worse of the two solutions):
public class Reptile extends Animal{
public void breed(){
throw new UnsupportedOperationException("Don't call Reptile#breed!!");
}
}
This solution is particularly bad, because if you don't have proper error handling, this exception will propagate all the way up the stack to your main method, and if there is not exception handling for this all the way to your main method, then your program crashes.
I recommend choice A, personally.

Another version of #earchengine's answer, add a couple of interfaces:
public abstract class Animal{
public abstract void fooMethod();
}
public class Breed {...}
public interface Bred {
Breed breed();
}
enum Gender { ...}
public interface Gendered
Gender gender();
}
public class Reptile extends Animal {
public void fooMethod(){}
}
public class Cat extends Animal implements Gendered, Bred {
public void fooMethod(){}
public Breed breed(){}
public Gender gender(){}
}
public class Dog extends Animal implements Gendered, Bred {
public void fooMethod(){}
public Breed breed(){}
public Gender gender(){}
}

Related

Java - class extending abstract class and implementing an interface having same methods

like in topic. Here's an example:
public abstract class Bird{
public abstract void eat();
public abstract void fly();
}
public interface Flyable{
public void fly();
}
public class Test extends Bird implements Flyable{
public void eat(){
System.out.println("I'm eating");
}
// And what's now?
public void fly(){
}
}
And now, there is main question. What happens. Is an error being throwed, or fly is same for interface and abstract class?
Nothing happens. Just implement your logic inside fly() and be happy.
If the methods have the same signature, everything will be fine. It is also okay to have the implementation in the abstract class or to implement a method which is specified in multiple interfaces of the class.
In Java, a method is identified by its name and its parameters. Consequently, the return type of the implemented method must be compatible with all return types of all specified methods with the same identifier. The same applies to the throw clauses. If the return type or throw clauses of the implemented method are incompatible, you will get a compilation error.
This example is not working:
public interface Flyable {
void eat();
void fly();
}
public abstract class Bird {
public int eat() {
return 500;
}
public void fly() throws StallException {
}
}
public class Eagle extends Bird implements Flyable {
}
Eagle.java, line 1: Exception StallException in throws clause of Bird.fly() is not compatible with Flyable.fly()
Eagle.java, line 1: The return types are incompatible for the inherited methods Flyable.eat(), Bird.eat()

Enforcing instance variable implementation from an abstract class in Java

I am trying to design an abstract class which will enforce implementation of an instance variable even though the type if this instance variable is unknown at the abstract level. For example:
public abstract class AbstractDiet{
abstract void computeMeat()
abstract void computeVeggies()
…
}
public abstract class AbstractAnimal{
protected AbstractDiet diet;
…
}
Then I'd like users to implement something like:
public class Cat extends AbstractAnimal{
protected CatFoodDiet diet; // CatFoodDiet extends AbstractDiet
…
}
Is this the best way to implement the diet variable? I want to ENFORCE that a subclass of AbstractDiet is always implemented in a subclass of AbstractAnimal.
First of all: Keep your instance variables private, and provide accessor methods.
Second of all: It sounds like you are trying to define an interface. Use an interface any time you want to say something like, "every animal has a diet."
interface Animal {
Diet getDiet();
...
}
If you like, you can also incorporate Bohemian's idea, and make it generic.
interface Animal<D extends Diet> {
D getDiet();
...
}
That way, you will have maximum freedom when it comes time to define different kinds of animal
class Cat implements Animal<CatDiet> {
CatDiet getDiet() { return...; }
}
You can't (and shouldn't) approach the design like that. Using abstract classes, try something like this:
public abstract class AbstractDiet {
abstract void compute();
}
public abstract class AbstractAnimal<T extends AbstractDiet> {
protected T diet;
}
public class CatFoodDiet extends AbstractDiet {
compute() {
//
}
}
public class Cat extends AbstractAnimal<CatFoodDiet> {
// use field in super which is type CatFoodDiet
}
But typically you would use interfaces instead of abstract classes for the abstract types.
The most flexible way is to just require the subclass to provide the information:
public abstract class AbstractAnimal {
// Subclasses must provide a function that returns the diet
public abstract AbstractDiet getDiet();
}
public class PetRock extends AbstractAnimal {
#Override
public AbstractDiet getDiet() {
return new SunlightDiet();
}
}
If you want to force a particular implementation, this is a common way:
public abstract class AbstractAnimal {
private AbstractDiet diet;
// Provide a constructor that sets a diet
protected AbstractAnimal(AbstractDiet aDiet) {
if (null == aDiet)
throw new NullPointerException("Diet must be specified");
diet = aDiet;
}
public class PetRock extends AbstractAnimal {
public PetRock() {
// Subclasses have to provide a diet to the superclass
super(new SunlightDiet());
}
}

Avoid using instanceOf in observer method

I have the following system in Java:
public class Human {
public void drown(Animal animal) {
if (animal instanceOf Fish) {
return;
} else {
animal.die();
}
}
}
public abstract class LandAnimal extends Animal{...}
public class Tiger extends LandAnimal{...}
public abstract class Fish extends Animal {...}
public class Trout extends Fish {...}
I have thought of adding a method
public abstract boolean drownable() {...}
in class Animal but I don't have access to the code of Animal class.
As I know the use of instanceOf is considered bad OOP practice. How do I avoid the use of instanceOf in this case? Thanks.
The drown() method in Human should be (by the way, why do humans want to drown animals?):
public void drown(Animal animal) {
animal.drown();
}
And each Animal will know what to do, for example:
// in class Tiger
public void drown() {
die();
}
// in class Fish
public void drown() {
// do nothing, fish can't drown
}
You would declare Animal.drown() and override it in Fish, containing the appropriate 'kill code' :).
So you'd just need to call drown() on each animal and each instance will behave according to its type specific method implementation.
public class Human {
public void drown(Animal animal) {
animal.drown();
}
}
Methods can be overloaded based on their arguments. You can have two different methods:
public void drown(Fish f) {
return;
}
public void drown(LandAnimal a) {
a.drown();
}
However, it should be noted that this makes determining whether some animal will drown the responsibility of the Human class, which, as other answers show, is arguable.

Creating new object in abstract class in Java

I have two objects which use really similar methods, save for one line. For example:
public class Cat extends Animal
public class Dog extends Animal
And they both use a breed method in the abstract class Animal. One calls new Dog(), and the other new Cat(). Right now I just have it declared as abstract public void breed(); in Animal, but is there a way I can generalize it so I don't have to make it an abstract method to be overridden?
There are many ways to do this, assuming by breed you mean "create children of me."
Reflection
First is to use reflection. If you have a no-args constructor for your classes, this is as easy as calling Class.newInstance:
public Animal breed() {
try {
return (Animal) getClass().newInstance();
} catch (Exception ex) {
// TODO Log me
return null;
}
}
If you don't have a no-args constructor in all your subclasses, you'll have to have a uniform constructor across all your subclasses. For example, if you have Cat(int, String) and Dog(int, String), then you need to get the constructor via Class.getConstructor and invoke newInstance on that:
return (Animal) getClass().getConstructor(int.class, String.class).newInstance(0, "Unnamed");
int and String here may be age and name, for example. This is how you do this with reflection.
Providers
Another way is to use this simple interface:
public interface Provider<T> {
T create();
}
Then have your abstract class take an instance of this in its constructor:
public abstract class Animal {
private final Provider<Animal> animalProvider;
protected Animal( ... , Provider<Animal> animalProvider) {
// ...
this.animalProvider = animalProvider;
}
public Animal breed() {
return animalProvider.create();
}
}
Then your subclasses will pass a Provider<Animal> to the superclass which will create new instances of the subclass:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new DogProvider());
// ...
}
private static class DogProvider implements Provider<Animal> {
public Animal create() {
return new Dog( ... );
}
}
}
Do the same for other subclasses as well.
Note: if by breed you mean "get the type of me," then you should edit your question to say so. If this is what you meant, then this is a viable solution:
public abstract class Animal {
protected final Breed breed;
protected Animal( ... , Breed breed) {
// ...
this.breed = breed;
}
public Breed getBreed() {
return breed;
}
}
I recommend following the get/set conventions for data container methods. Java has bean classes designed to handle these naming conventions, and it's more or less a standard across many platforms. For your subclasses:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new Breed( ... ));
// ...
}
}
Actually, yes you can. You need to use reflection so performance could be a little iffy, but this (untested) should work:
public abstract class Animal{
public Animal breed(){
return getClass().newInstance();
}
//other methods
}
This will return a new instance of the actual calling type, not the type of Animal (where it's implemented).
This is actually somewhat similar to the Prototype Pattern. Although in this case you're creating a new instance, not copying an existing instance.
Edit
As #FrankPavageau pointed out in the comments, rather than masking an exception in the constructor, you can achieve the same result by using
public abstract class Animal{
public Animal breed(){
return getClass().getConstructor().newInstance();
}
//other methods
}
Which will wrap any exception thrown in an InvocationTargetException which is a bit cleaner and probably easier to debug. Thanks #FrankPavageau for that suggestion.
No there isn't. You will have to have something like what you have done as below
I think you want to have in your abstract class
public abstract Breed getBreed();
and then in each sub class have
public Breed getBreed() {
return new DogBreed();
}
and a similar one returning cat.
or
Have a protected field in the Animal class called breed. This could then be initialised in each of the subclasses. This would remove the need for an abstract method. For example
public abstract class Animal {
Breed breed;
...
}
and then in Dog have
public class Dog extends Animal {
public Dog() {
breed = new DogBreed();
}
}
and have something similar to Cat.
It might be worth you while also passing in the breed to the Dog/Cat ctor so that you can create Dog objects of different breeds rather than restricting your model to just one breed of Dog
I am not sure Breed is necessarily modelled correctly in your example. Do you really want new Dog() to be a breed? Or do you mean type? In which case it is just an animal and the abstract method returning animal is the way to go.

Purpose of having abstract child by extending concrete parent

Sometimes, I came across some class design as follow.
abstract class animal {
public abstract void speak();
}
class dog extends animal {
#Override
public void speak() {
// Do something.
}
}
abstract class abstract_dog extends dog {
#Override
public abstract void speak();
}
I was wondering, what is the purpose of having an abstract_dog class? Why we "transform" the non-abstract speak method into abstract speak again?
In case you want to create a base class that forces people to override speak, but inherits Dog.
I agree with SLaks, and think that this would be a real life situation:
abstract class animal {
public abstract void speak();
}
class dog extends animal {
#Override
public void speak() {
// Dog says 'bark'
}
}
abstract class abstract_dog extends dog {
#Override
public abstract void speak();
}
class poodle extends abstract_dog {
#Override
public void speak() {
// poodle says 'yip yip'
}
}
class great_dane extends abstract_dog {
#Override
public void speak() {
// great dane says 'ruff ruff'
}
}
I think you would use this in the case where you want the make a new child class implement the speak method and the dog class may have other methods that the new child class would not have to implement.
Knowing more about your exact situation would help in determining if there is a better design for this scenario.

Categories