简体   繁体   English

超类可以将其子类静态地存储在列表中吗?

[英]Can a superclass store its subclasses in a list statically?

I have a super class, SuperClass. 我有一个超级班,超级班。 I want a JList displaying every subclass of SuperClass. 我想要一个JList显示SuperClass的每个子类。 Not how many subclasses of SuperClass were instantiated, but how many subclasses I have actually defined in my program. 不是实例化SuperClass的多少个子类,而是我在程序中实际定义了多少个子类。 The point is that it should be easy to add new subclasses without changing code anywhere else. 关键是应该很容易添加新的子类,而无需更改其他任何地方的代码。

I'm hoping that my SuperClass can define a static map that would increase for every subclass I define (not instantiate). 我希望我的超类可以定义一个静态映射,该映射对于我定义的每个子类都会增加(而不是实例化)。 Now by clicking on the items of the JList the appropriate subclasses should be instantiated. 现在,通过单击JList的项目,应实例化适当的子类。

I will try to show what I want to do: 我将尝试展示我想做什么:

public abstract class SuperClass {
    protected static ArrayList<?extends SuperClass> subclasses = new ArrayList<>();
}
class SubClassOne extends SuperClass {
    static {
        subclasses.add(this)
    }
}

Now I realize there are lots of problems with above code, but I hope it clarifies what I want. 现在,我意识到上面的代码存在很多问题,但是我希望它可以阐明我想要的内容。 I'm entirely clueless how I should proceed with regards to instantiating my subclasses from the JList. 我完全不知道如何从JList实例化我的子类。

Please specify if I can give any more information that could be of help. 请指定我是否可以提供其他任何有帮助的信息。

You can use a static initializer block in your subclasses: 您可以在子类中使用静态初始化程序块:

public class MySubclass extends MySuperclass {

    static {
        MySuperclass.register(MySubclass.class);
    }
}

then in your superclass you can have a register method like this: 然后在您的超类中,您可以有一个如下的register方法:

protected static void reigster(Class<?> clazz) {
    subclasses.add(clazz);
}

Then when you want to instantiate a class: 然后,当您要实例化一个类时:

MySuperclass subclassInstance = subclasses.get(someIndex).newInstance();

Note that this only works if you actually load those classes. 请注意,这仅在您实际加载这些类时才有效。 For dynamic class loading you might have to implement your own ClassLoader or use some dynamic OSGi framework like the Apache Felix. 对于动态类加载,您可能必须实现自己的ClassLoader或使用诸如Apache Felix之类的动态OSGi框架。

Approach 1: 方法1:

public abstract class SuperClass {
    protected static ArrayList<Class<? extends SuperClass>> subclasses = new ArrayList<>();
}
class SubClassOne extends SuperClass {
    static {
        subclasses.add(SubClassOne.class);
    }
 }

Approach 2 方法2

Scan entire classpath (using reflection), iterate for each class and check if the class inherits from your superclass. 扫描整个类路径(使用反射),为每个类进行迭代,并检查该类是否继承自您的超类。
You could look into Reflections library . 您可以查看Reflections库 I'd do it for you in an easy way. 我会为您轻松完成此操作。

Hope this helps. 希望这可以帮助。

As demonstrated by the other answers, it is not suited for inheritance . 如其他答案所示,它不适合继承 Rather look at the factory pattern: some factory class that holds (a map of) classes, and it can instantiate objects of one of those classes. 而是看一下工厂模式:一些工厂类保存(映射)类,并且可以实例化其中一个类的对象。

There are some standard mechanisms in Java. Java中有一些标准机制。

  1. You could make your own annotation; 您可以自己做注释; use annotation processing 使用注释处理

     @Factored public class A { } @Factored public class B { } 

    This is a large coding overhead. 这是很大的编码开销。

  2. You could use the java service provider interface 您可以使用Java 服务提供商接口

    This SPI is used for detecting XML parsers and such, where jars on the class path have a file under MANIFEST with a text file with a file name the interface class path. 此SPI用于检测XML解析器等,其中类路径上的jar包含MANIFEST下的一个文件,该文件的文本文件的名称为接口类路径。 In it one or more implementation classes may be listed. 其中可以列出一个或多个实现类。 These implementations can then be listed. 然后可以列出这些实现。

    This is a declarative approach, so lacks the desired automatism. 这是一种声明性方法,因此缺少所需的自动性。

  3. Make an enum of factories 列举工厂

    Suitable only for a limited close-world set of classes, also giving strong dependencies. 仅适用于有限的近距离类集,也具有很强的依赖性。

     public enum Factory<T> { F_A(A.class), F_B(B.class); private static final Set<Class<T>> klasses = new HashSet<>(); static { for (Factory f : values()) { klasses.add(f.klass); } } public final Class<T> klass; private Factory(Class<T> klass) { this.klass = klass; } //public <S extends T> S instantiate(Class<S> kl) { public T instantiate() { ... } } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM