【问题标题】:Creating an instance of a subclass extending an abstract class (Java)创建扩展抽象类 (Java) 的子类的实例
【发布时间】:2010-06-08 21:35:21
【问题描述】:

在 Java 中,有没有办法在类 A 的成员方法中创建扩展抽象类 A 的任何类的实例?扩展抽象类 A 的类将使用此方法返回它们的实例,但我不想在所有子类中使用“return this();”实现相同的方法;亲切的线条。

编辑:好的,很抱歉简短的解释。在我的应用程序中,有一个名为 Application 的接口,它有一个返回 Application 类型的 getInstance() 方法。有一个抽象类叫AbstractApplication,它是Application接口实现的便利类,但只有接口暴露在其他应用程序中。在其他一些应用程序中,会有一个应用程序对象的查找,这个查找将返回一个应用程序类型(接口),而不是一个具体的实现。现在这是我的问题;有没有办法在 AbstractApplication 类中实现 getInstance() 所以子类不需要实现这个方法?

【问题讨论】:

  • 愿意为您要实现的目标提供一些伪代码吗?
  • 要么为时已晚,要么还不清楚你想做什么。你能举个例子(代码)吗?我确信这应该是可能的,但是,唉,我真的不明白你想首先做什么。
  • 问题是,你为什么需要自己返回的东西?
  • @Andrei 我认为这个问题需要解释为一种返回同一实现类的新实例的方法。
  • 我唯一的问题是,谁首先创建了应用程序?对于直到运行时才知道应用程序的场景,您可以使用原型设计模式。请参阅下面的答案。

标签: java oop


【解决方案1】:

是的。这很容易(除非我误解了)

您必须使用原型设计模式(或我在这里展示的它的变体)

当您直到运行时才知道工厂类可能是什么时,它很有用。与 AbstractFactory 不同,您可以使用不同的子类创建新类型,但您可以根据特定条件选择一个。

使用原型,您可以简单地将“原始”对象(原型)注入您的应用程序(借助完整的未来依赖注入框架或简单的类名),然后创建它的新实例。

这是一个示例代码,展示了如何使用变体执行此操作(不使用 clone 而是使用 newInstance 方法)

public abstract class Application {
    public Application newInstance() {
        try {
            return this.getClass().newInstance();//this creates an instance of the subclass 
        } catch( InstantiationException ie ){
            throw new RuntimeException( ie );
        } catch( IllegalAccessException iae ){
            throw new RuntimeException( iae );
        }
    }
    public String toString() {
        return "This is the class named: \""+ this.getClass().getSimpleName()+"\"";
    }
} 
// subclasses doesn't repeat the creation part
// they just have to override specific methods. 
class FirstClass extends Application {}
class SecondClass extends Application {}
class ThirdClass extends Application {}

您的其余代码可能会编程到Application 接口:

public void doSomethingWith( Application application ) {
        System.out.println( application.toString() );
}
public void startApplication( Application app ) {
    // etc etc 
}

每当您需要一个新实例时,您只需调用:

Application newApp = original.newInstance();

这将创建正确的类型。

正如您所见,子类没有指定如何创建新的子类,这一切都在基类中。

调用newInstance 方法总是会创建一个相同类型的新实例。

【讨论】:

  • 嗯...对我来说仍然是一个可怕的设计错误。此外,依赖于每个子类都有一个无参数构造函数。
  • 这可能是因为我们... 不同 接触到软件开发。但说实话,这个想法根本不是我的想法。书中描述了它:Design Patterns: Elements of Reusable Object-Oriented Software 它解决的主要问题是在运行时指定工厂(当你不知道你将使用什么类型的对象时)创建)
【解决方案2】:

如果超类知道它的子类,这表明设计不佳。

实现这样的事情的正常方法是拥有一个受保护的抽象方法,子类必须实现该方法才能返回特定于子类的结果。

【讨论】:

【解决方案3】:

我对我的 Java 有点生疏,但我相信在超类(在此示例中为类 A)中执行的反射代码会认为它是子类的一部分。

例子:

public abstract class A
{
   public abstract void Something();
   public A Create()
   {
       Class me = this.getType(); // Returns a Reflective "Class" object for the SUB-Type
       // Use this object to reflectively instantiate a new instance, cast it as an A
       object obj = ReflectiveInstantiationHere(ItsBeenAWhile, SoGoogleThisPlease);

       return (A)obj;
   }
}

public class B extends A
{
   public void Something() 
   {
      A newInstanceOfB = Create();
   }
}

当然,您可以在检查类型之后将返回的值从 A 转换为 B :)

【讨论】:

    【解决方案4】:

    这样的?

     abstract class Abs{
        public <T extends Abs> T getInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException {
            return clazz.newInstance();
        }
     }
    

    虽然这并不能保证你会得到一个你调用它的类的实例。为此,您仍然需要执行以下操作:

    class Abs1 extends Abs {
        public Abs1 getInstance() { return super.getInstance(Abs1.class) }
    }
    

    所以没有太大的改进。

    我认为这里的结论是,如果您只在父类中声明方法抽象,并在扩展它的每个类中使用new WhateverClassImIn() 实现它,那么您最终会得到更少的代码和更少的麻烦。你可以(可能)按照你想要的方式去做,但这不值得。

    【讨论】:

      【解决方案5】:

      您可以做到,但只能使用hackery。我相信其他人会提供详细信息。

      这是一个有点奇怪的设计。你不应该真正关心具体的实现——坚持接口。在不改变设计的情况下,您能做的最好的事情是:

      protected abstract A createCompatibleInstance();
      

      让子类实现它。

      但是很糟糕。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多