我正在使用我公司的API,我想为现有对象创建一个子类。以下是警告:
我最常见的例子是Dog作为Animal的子类,所以我将使用它。假设你在API中有这个类:
//API class, which I cannot modify
public class Animal(){
public void eat(){
//All animals can do this
}
}
现在我想创建一个这样的类,它为Animal添加了一些方法。
//My subclass, which I can modify
public class Dog extends Animal(){
public void fetch(){
//Only dogs can do this
}
}
所以现在让我说我有一个动物实例(一个不是狗)。我基本上需要把它变成一只狗。我认为Java中没有直接支持这种向下转换,但有没有解决方法呢?
public class AnimalExample{
public static void main(String[] args){
Animal animal = MyApi.getAnAnimal();
//Dog dog = (Dog) animal; ---throws a runtime error
Dog dog = Dog.getDog(animal); //Maybe something like this?
//Then I should be able to call both eat() and fetch()
dog.eat();
dog.fetch();
}
}
同样,我理解不直接支持向下转换。但是必须有一些解决方法,我无法弄明白。我知道我可以使用包装类(例如DogWrapper
),但这比我想要的要困难一些,因为我仍经常调用几十种超类方法。
更新:我知道它还不是狗,但我想知道是否有办法将它转换为狗。从人们的说法来看,它基本上听起来像我必须手动转换它(逐个复制每个属性/方法)或者只使用Wrapper类。一个Wrapper类似乎不那么混乱,所以不幸的是我只需要去那条路。因此,DogWrapper
将采用fetch()
方法和getAnimal()
方法。所以,如果我想让Dog
吃,那么我必须致电dog.getAnimal().eat()
。我不必这样做,但我想没有办法解决它。有没有人看到比这更简单的东西?
答案 0 :(得分:0)
你可以有一个构造函数,它接受Animal并使用默认值或根据需要实例化对象的Dog部分。
public Dog (Animal animal) {
super(); // any instantiation that has to be done for animal
// Dog instantiation
// Use animal properties as required
}
Dog dog = new Dog(animal);
如上所述,Dog.getDog(animal)
提供静态方法也是一种选择,具体取决于您的编码偏好。
答案 1 :(得分:0)
我们假设我创建了一个需要Dog
的方法,但这意味着要扩展Animal
API。当然,我可以像这样签名:
public void doFetch(Dog dog)
但正如我所说,我想扩展Animal
API。现在,如果给定的Animal
不是Dog
,我就无法获取。考虑到这一点,我可以做到以下几点:
public void doFetch(Animal fetcher) {
if(fetcher instanceof Dog) {
Dog dog = (Dog) fetcher;
... //Do fetchy things
return;
}
//If we reach this point, then the animal is not a dog
throw new IllegalArgumentException("fetcher is not a Dog!");
}
现在让我们假设,就像你的情况一样,我有一只不是狗的Animal
,但出于某种原因我希望它是Dog
。在这种情况下,我可以使用某种翻译器将任何Animal
转换为狗。我更喜欢将此类内容定义为static
类本身中的Dog
方法:
//Breaks the laws of nature by making a Dog from any Animal.
public static Dog fromAnimal(Animal animal) {
Dog dog = new Dog();
//Here you would set all the properties of the animal, e.g.:
dog.setName(animal.getName());
...
return dog;
}