2012-09-22 73 views
5

我有两个对象使用真正类似的方法,只保存一行。例如:在Java中创建抽象类中的新对象

public class Cat extends Animal 
public class Dog extends Animal 

,他们都使用抽象类Animal一个breed方法。一个叫new Dog(),另一个叫new Cat()。现在我只是在Animal中声明它为abstract public void breed();,但是有没有办法将它推广,所以我不必将其作为一个被覆盖的抽象方法?

+0

是的,它是没有必要的,在一个类中的所有方法都需要是抽象 –

+1

@SashiKant虽然如此,我不认为这是OP是问什么...... –

回答

3

有很多方法可以做到这一点,假设你的意思是“创造我的孩子”。

反射

首先是使用反射。如果你有你的类无参数的构造,这是因为调用Class.newInstance一样容易:

public Animal breed() { 
    try { 
     return (Animal) getClass().newInstance(); 
    } catch (Exception ex) { 
     // TODO Log me 
     return null; 
    } 
} 

如果你没有在所有的子类的无参数的构造函数,你必须有一个统一的构造函数遍历所有的子类。举例来说,如果你有Cat(int, String)Dog(int, String),那么你就需要通过Class.getConstructor得到构造函数和调用上newInstance

return (Animal) getClass().getConstructor(int.class, String.class).newInstance(0, "Unnamed"); 

intString这里可能是年龄和名字,例如。这就是你如何用反射来做到这一点。

提供商

另一种方法是使用这个简单的接口:

public interface Provider<T> { 
    T create(); 
} 

然后让你的抽象类采取了这样的一个实例在其构造:

public abstract class Animal { 
    private final Provider<Animal> animalProvider; 

    protected Animal(... , Provider<Animal> animalProvider) { 
     // ... 
     this.animalProvider = animalProvider; 
    } 

    public Animal breed() { 
     return animalProvider.create(); 
    } 
} 

然后你子类会将Provider<Animal>传递给超类,它将创建子类的新实例:

public class Dog extends Animal { 
    public Dog(...) { 
     super(... , new DogProvider()); 
     // ... 
    } 

    private static class DogProvider implements Provider<Animal> { 
     public Animal create() { 
      return new Dog(...); 
     } 
    } 
} 

对其他子类也做同样的事情。

注意:如果通过breed您的意思是“得到我的类型”,那么你应该编辑你的问题说出来。如果这是你的意思,那么这是一个可行的解决方案:

public abstract class Animal { 
    protected final Breed breed; 

    protected Animal(... , Breed breed) { 
     // ... 
     this.breed = breed; 
    } 

    public Breed getBreed() { 
     return breed; 
    } 
} 

我建议您按照get/set约定数据容器的方法。 Java拥有旨在处理这些命名约定的bean类,它在很多平台上或多或少都是标准。为了您的子类:

public class Dog extends Animal { 
    public Dog(...) { 
     super(... , new Breed(...)); 
     // ... 
    } 
} 
2

不,没有。你必须有一些像你做了什么,如下

我想你想在你的抽象类有

public abstract Breed getBreed(); 

,然后在每个子类有

public Breed getBreed() { 
    return new DogBreed(); 
} 

和类似的一只回归的猫。

已经在动物类中调用一个品种保护地。这可以在每个子类中初始化。这将消除对抽象方法的需求。例如

public abstract class Animal { 
    Breed breed; 
... 
} 

,然后在狗有

public class Dog extends Animal { 
    public Dog() { 
     breed = new DogBreed(); 
    } 
} 

,并有类似猫的东西。

这可能是值得您同时还通过在品种的狗/猫构造函数,这样就可以创造出不同品种的狗的对象,而不是限制你的模型狗

的只是一个品种,我不知道在您的示例中,品种必须正确建模。你真的想要新的Dog()成为一个品种吗?或者你的意思是打字?在这种情况下,它只是一种动物,而回归动物的抽象方法就是要走的路。

3

其实,你可以。你需要使用反射这样的表现可能会有点玄乎,但这种(未经测试)应该工作:

public abstract class Animal{ 
    public Animal breed(){ 
     return getClass().newInstance(); 
    } 
    //other methods 
} 

这将返回实际调用类型的新实例,而不是动物(其中它的实现)的类型。

这实际上有些类似于Prototype Pattern。虽然在这种情况下你正在创建一个新的实例,而不是复制一个现有的实例。

编辑

由于@FrankPavageau在评论中指出,而不是掩盖在构造异常,您可以通过使用

public abstract class Animal{ 
    public Animal breed(){ 
     return getClass().getConstructor().newInstance(); 
    } 
    //other methods 
} 

这将包装抛出的任何异常达到同样的效果在InvocationTargetException这是一个更清洁,可能更容易调试。感谢@FrankPavageau对此建议。

+0

试过,但它抛出了'InstantiationException'。 –

+0

@ Eng.Fouad做了它还是说它需要捕捉它?有很多这方面的例子在网络上运作。 –

+0

是的,它抛出'InstantiationException'。你可以自己试试:) –