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

huangapple go评论59阅读模式
英文:

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

问题

我刚开始学习Java编程请考虑以下代码片段

public class Animal {
    public void mate( /*我应该在这里放什么?*/ anotherAnimal ) {
    }
}

public class Cat extends Animal {
}

public class Dog extends Animal {
}

我希望以这样的方式编写方法``Animal.mate()``,当从子类对象调用该方法时传递给方法的参数必须是相同子类的对象否则会触发编译错误例如

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

cat.mate( dog ); // 引发编译错误
cat.mate( randomAnimal ); // 编译错误
cat.mate( trueLove ); // 通过编译检查

我所询问的是否可能我有一种模糊的感觉可能可以使用泛型来实现
英文:

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.

答案1

得分: 1

以下是您要翻译的内容:

无法使编译器阻止所有不良调用。即使将Animal参数化,仍然可能在运行时执行诸如cat.mate(dog)的操作。

如果您的业务逻辑要求这样做,那么最好的方法是使用类似以下方式进行验证:

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

如果您这样做主要是为了改进编译时的类型检查,那么您可以使用泛型,了解其局限性:

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

    }
}

如果API用户使用子类而不是Animal类型,并且不使用原始类型,则这将起作用。

Cat c = new Cat();
c.mate(new Cat());
c.mate(new Dog()); //失败

Animal animal = c; //原始类型
animal.mate(new Dog()); //仅产生警告
英文:

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&lt;T extends Animal&lt;T&gt;&gt; {
	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

答案2

得分: 0

你的问题涉及多态性。在mate方法中使用超类作为参数类型。超类是Animal。以下是代码部分:

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";
    }
}

main方法中运行你的代码,错误将被修复,输出如下:

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

为了得到更好的答案,你可以在Animal类中定义一个name字段。

英文:

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(&quot;Animals mating&quot;);
}
@Override
public String toString() {
    return &quot;Animal&quot;;
}

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

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

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.

huangapple
  • 本文由 发表于 2020年8月31日 20:26:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63670814.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定