创建扩展抽象类的子类的实例(Java)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3001490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:53:44  来源:igfitidea点击:

Creating an instance of a subclass extending an abstract class (Java)

javaoop

提问by Deniz Acay

In Java, is there any way to create an instance of any class that extends abstract class A, inside a member method of class A? Classes that extends abstract class A will return their instances with this method, but i don't want to implement same method in all subclasses with a "return this();" kind line.

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

EDIT: Ok sorry for the short explanation. In my application, there is an interface called Application, and it has a getInstance() method that returns an Application type. There is an abstract class called AbstractApplication which is a convenience class for Application interface for implementation, but only the interface is exposed in other apps. In some other apps, there will be a lookup for application objects, and this lookup will return an Application type (interface), not a specific implementation. Now here's my question; is there a way to implement getInstance() in AbstractApplication class so subclasses does not need to implement this method?

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

回答by OscarRyz

Yeap. That's pretty easy ( unless I misunderstood )

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

You have to use the Prototype design pattern ( or a variation of it that I show here )

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

It is useful when you don't know what the factory class could be until runtime. Unlike AbstractFactory where you can have different subclasses creating new types but you may pick one based on certain conditions.

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

With prototype you may simple get the "original" object ( the prototype ) injected into your application ( by virtue of a full futured Dependency Injection framework or by a simple class name ) and then create new instances of it.

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

Here's a sample code showing how to do this with a variation ( not using clonebut newInstancemethod )

这是一个示例代码,显示了如何使用变体(不使用clonenewInstance方法)来执行此操作

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 {}

And the rest of your code may program to the Applicationinterface:

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

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

Whenever you need a new instance you just call:

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

Application newApp = original.newInstance();

And that would create the correct type.

这将创建正确的类型。

As you see the subclasses doesn't specify how to create new subclasses, that's all in the base class.

正如您所看到的,子类没有指定如何创建新的子类,这些都在基类中。

Invoking the method newInstancewill always create a new instance which of the same type.

调用该方法newInstance将始终创建一个相同类型的新实例。

回答by dty

If a superclass knows about its subclasses, this points to poor design.

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

The normal way of achieving something like this is to have a protected abstract method which subclasses must implement to return a subclass-specific result.

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

回答by Andrei Fierbinteanu

Something like this?

像这样的东西?

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

Though this does not guarantee you'll get an instance of the class you're calling it from. To do that you'd still have to do something like:

尽管这并不能保证您会获得从中调用它的类的实例。为此,您仍然必须执行以下操作:

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

so not much of an improvement there.

所以没有太大的改进。

I think the conclusion here is you'll end up with a lot less code and a lot less headaches if you just declare the method abstract in the parent, and implement it with new WhateverClassImIn()in every class that extends it. You can (probably) do it the way you want to, but it's not gonna be worth the effort.

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

回答by Aren

I'm a bit rusty on my Java, but I believe that reflectively code executing in the super-class (in this example class A) will think it's part of the subclass.

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

Example:

例子:

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();
   }
}

You can cast the returned value from A into a B later after checking types of course :)

您可以稍后在检查类型后将 A 的返回值转换为 B :)

回答by Tom Hawtin - tackline

You can do it, but only with hackery. I'm sure other people will give details.

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

It's a bit of an odd design. You shouldn't really care about specific implementations - stick to the interfaces. The best you can do without changing the design much is:

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

protected abstract A createCompatibleInstance();

Have subclasses implement it.

让子类实现它。

But yuck.

但是糟糕。