简体   繁体   中英

How to write a method in superclass whose parameter type is restricted to another object belonging to the same subclass of the calling object

I'm new to Java programming. Please consider the following code snippet.

public class Animal {
    public void mate( /*what should I put here?*/ anotherAnimal ) {
    }
}

public class Cat extends Animal {
}

public class Dog extends Animal {
}

I want to write the method Animal.mate() in such a way that, when the method is called from a subclass object, the argument fed to the method must be an object of the same subclass, otherwise a compiler error is triggered. For instance:

Cat cat = new Cat();
Dog dog = new Dog();
Animal randomAnimal = new Animal();
Cat trueLove = new Cat();

cat.mate( dog ); // raises a compiler error
cat.mate( randomAnimal ); //compiler error
cat.mate( trueLove ); //passes compiler check

Is what I'm asking possible? I have a vague feeling that it might be possible to do it using generics.

There's no way to make the compiler prevent all bad calls. Even if you parameterize Animal , it would still be possible for something like cat.mate(dog) to be executed at runtime.

If this is required by your business logic, then your best bet is to validate, with something like :

public class Animal {
    public final void mate(Animal anotherAnimal ) {
        if(!this.getClass().equals(anotherAnimal.getClass())) {
            throw new IllegalArgumentException();
        }
    }
}

If you're doing this mainly to improve compile-time type checking, then you can use generics, knowing the limitations:

class Animal<T extends Animal<T>> {
    public final void mate(T anotherAnimal) {

    }
}

This will work if your API users use the subclasses rather than the Animal type, and they don't use raw types.

Cat c = new Cat();
c.mate(new Cat());
c.mate(new Dog());//fails

Animal animal = c;      //raw type
animal.mate(new Dog()); //only a warning

your problem is about to Polymorphism. use super class as parameter type in mate method.super class is Animal. this is the code:

public class Animal {
public void mate(Animal animal) {
    System.out.println("Animals mating");
}
@Override
public String toString() {
    return "Animal";
}

public class Dog extends Animal {
@Override
public String toString() {
    return "Dog";
}
public class Cat extends Animal {
@Override
public void mate(Animal obj) {
    System.out.println("cat mating with " + obj );
}

@Override
public String toString() {
    return "cat";
}}

and run your code in main method. errors have gone and this is the answer:

cat mating with Dog.
cat mating with Animal.
cat mating with cat.

for better answer instead of saying cat or dog, you can define a name field in Animal class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM