Java 如何从另一个类的静态方法中获取抽象类的子类的实例?

Java 如何从另一个类的静态方法中获取抽象类的子类的实例?,java,static,abstract-class,subclass,instance-variables,Java,Static,Abstract Class,Subclass,Instance Variables,我的班级结构如下: 数据存储类: 父类:PStore:公共抽象类PStore… 扩展它的两个子类:CStore1和CStore2 每个子类都是一个N-glton(抱歉,不确定它的Java术语是什么)——它只能有N个实例,编号为1..NMax 每个子类都有以下访问该实例的方法:CStore1.getInstance(Id)和CStore2.getInstance(Id) 工人阶级: 父类:公共抽象类PWork… 扩展它的两个子类:CWork1和CWork2 当前情况: ClassCWo

我的班级结构如下:

  • 数据存储类:

    • 父类:
      PStore
      公共抽象类PStore…
    • 扩展它的两个子类:
      CStore1
      CStore2
    • 每个子类都是一个N-glton(抱歉,不确定它的Java术语是什么)——它只能有N个实例,编号为1..NMax
    • 每个子类都有以下访问该实例的方法:
      CStore1.getInstance(Id)
      CStore2.getInstance(Id)
  • 工人阶级:

    • 父类:
      公共抽象类PWork…
    • 扩展它的两个子类:
      CWork1
      CWork2
  • 当前情况:

    • Class
      CWork1
      实现了一个内部类,该类使用以下代码访问存储:

      protected class fListener implements ActionListener {
              public void actionPerformed(ActionEvent ae) {
                  CStore1.getInstance(Id).someMethod();
                  # NOTE: someMethod() is implemented in CStore2 as well
              }
          }
      
    • 我需要在
      CWork2

    • 作为一名优秀的小软件开发人员,我没有简单地将
      CWork1
      中的
      fListener
      复制/粘贴到
      CWork2
      类,然后在其代码中将
      CStore1
      更改为
      CStore2
      ,而是像个傻瓜一样决定将其迁移到父类


  • 我想做的是:

    • PStore
      中创建名为
      getStoreInstance(int-Id)
      的抽象方法:
      公共抽象PStore getStoreInstance(int-Id);
      

    • CStore1
      as
      publicpstoregetstoreinstance(int-Id){return CStore1.getInstance(Id);}

      到目前为止,一切顺利。它编译了所有3个存储类

    • 将fListener代码从
      PWork
      复制到
      CWork1

    • 显然,编译器抱怨它不知道任何关于CStore1类及其方法的信息

    • 现在,我决定只调用新创建的
      getStoreInstance()

      旧代码:
      CStore1.getInstance(Id).someMethod()

      新代码:
      PStore.getStoreInstance(Id).someMethod()

  • 编译器投诉:“无法从类型PStore对非静态方法getStoreInstance(Id)进行静态引用”

  • Eclipse提出的唯一“修复”方法是将getStoreInstance()方法设为静态,但这也不起作用:

    • 当我在抽象类的方法声明中添加了一个
      static
      修饰符时:
      publicstaticabstractpstore-getStoreInstance(int-Id)-编译器抱怨“PStore类型中的抽象方法getStoreInstance只能设置可见性修饰符,公共修饰符或受保护修饰符之一”

    • 当我试图使方法非抽象时:
      publicstaticpstore getStoreInstance(intid)它抱怨该方法需要一个主体(相当合理)

    • 当我尝试添加实体时,它要求我返回PStore对象。。。但是我的抽象类PStore没有构造函数,所以我无法返回PStore对象


我处理问题的方法正确吗?

如果没有,我应该如何处理它?


如果我是,那么我如何解决最初关于“无法对非静态方法进行静态引用”的抱怨,因为抽象类不允许我将该方法设置为静态方法?

编译器是正确的,因为在静态上下文中引用实例方法不起作用。在静态世界中,您在类级别上工作,处理整个类的属性。如果尝试调用实例方法,编译器如何知道要执行实例方法的实例

制作抽象方法是行不通的,因为抽象方法必须在子类中实现。但是,静态方法不能被重写——只能被隐藏。因此,如果在抽象方法上允许使用
static
,并且您尝试执行
AbstractClass.staticMethod()
,那么运行时将使用什么实现


你的代码有点难理解,但我是这么想的。仅根据名称,
getStoreInstance(intid)
实际上应该是一个静态方法,因为一个实例获取另一个实例没有多大意义;这似乎更像是全班应该做的事情。您可能需要重新思考如何构建代码。。。从代码名来看,您似乎应该有一种类级的方法来跟踪类的实例,因此,也许可以这样做,并将
getInstance()
getStoreInstance()
实现为静态方法,这将是一个开始?

在我看来,您有两个同构的类层次结构(如果我使用了正确的术语)并且相应的类之间存在关系:

      PStore                   PWork
      /     \                 /     \
     /       \               /       \
   CStore1  CStore2        CWork1   CWork2
      ^         ^              ^      ^  
      |         |              |      | 
      |---------+--------------|      |
                |                     |
                |---------------------|
但我认为Java中没有一种内置的方式来表达这种关系。 不知何故,您将不得不做一些事情来明确这些关系。例如,在
CWork1
中需要有一些内容引用
CStore1
,在
CWork2
中需要有一些内容引用
CStore2
,或者需要某种列表或映射来关联它们

可能有一种设计模式可以解决这种结构,但我现在想不起来。因此,在我的脑海中,有两种可能的解决方案(都不使用反射):

  • 将在
    PWork
    中定义的抽象
    getStoreInstance
    方法替换为
    PStore
    。在
    CWork1
    中,使用调用
    CStore1.getInstance
    的方法覆盖它
    class PWork {
    
        private static Map<Class<? extends PWork>,IntFunction<PStore>> storeMap;
        static {
            storeMap = new HashMap<>();
            storeMap.put(CWork1.class, CStore1::getInstance);
            storeMap.put(CWork2.class, CStore2::getInstance);
        }
    
        protected PStore getStoreInstance(int Id) {
            return storeMap.get(getClass()).apply(Id);
        }
    
        protected class fListener implements ActionListener {
            public void actionPerformed(ActionEvent ae) {
               int Id = ???; // I'm assuming Id is computed from ae somehow??
               getStoreInstance(Id).someMethod();
           }
        }
    
     }
    
    public class Worker<T extends PStore> {
        private final Class<T> c;
        public Worker(Class<T> c) {
            this.c = c;
        }
    
        public void actionPerformed(ActionEvent ae) {
            PStore.getInstance(c, Id).someMethod();
        }
        // other methods
    }
    
    public class PStore {
        private static Map<Class<?>, List<PStore>> map = new HashMap<>();
    
        protected PStore() {
            List<PStore> list = map.get(getClass());
            if (list == null) {
                list = new ArrayList<>();
                map.put(getClass(), list);
            }
            list.add(this);
        }
    
        public static PStore getInstance(Class<? extends PStore> c, int i) {
            return map.get(c).get(i);
        }
        public abstract void someMethod();
    }