簡體   English   中英

返回擴展抽象基類的具體類的類,而不是實例?

[英]Return a class, not an instance, of a concrete class that extends an abstract base class?

如果我有這樣的班級層次結構

AbstractSuperClass
    ConcreteClassA
    ConcreteClassB

是否可以在AbstractSuperClass使用靜態方法來返回兩個具體類之一的類(而不是實例)?

我嘗試返回Class<AbstractSuperClass> ,但是IDE(Android Studio)表示

Incompatible types.
Required: Class <com.example.AbstractSuperClass>
Found:    Class <com.example.ConcreteClassA>

這是我在想的例子,但是沒有用:

public abstract class AbstractSuperClass{

    public abstract void someAbstractMethod();


    public static String getSomeText(){ 
        return "This is AbstractSuperClass"; 
    };

    public static Class<AbstractSuperClass> getConcreteClass(int x){
        switch( x ){
            case 0: return ConcreteClassA.class;
            case 1: return ConcreteClassB.class;
        }
    }
}


public class ConcreteClassA extends AbstractSuperClass{
    public abstract void someAbstractMethod(){
        // Do something
    }

    public static String getSomeText(){ 
        return "This is ConcreteClassA"; 
    };
}



public class ConcreteClassB extends AbstractSuperClass{
    public abstract void someAbstractMethod(){
        // Do something
    }

    public static String getSomeText(){ 
        return "This is ConcreteClassB"; 
    };
}



AbstractSuperClass.getConcreteClass(1).getSomeText(); // Should return "This is ConcreteClassB"

這在Java中根本不可能嗎,還是我做錯了?

您不能像嘗試那樣直接從Class調用static方法,您將需要進行反射才能調用getSomeText()方法。 喜歡,

try {
    Method m = AbstractSuperClass.getConcreteClass(1).getMethod("getSomeText", 
            new Class[0]);
    System.out.println(m.invoke(null, new Object[0]));
} catch (Exception e) {
    e.printStackTrace();
}

然后,可以使用捕獲的擴展AbstractSuperClass (生產者擴展,消費者超級)來修復getConcreteClass方法。 如果沒有匹配項,則必須具有默認返回值。 喜歡,

public static Class<? extends AbstractSuperClass> getConcreteClass(int x) {
    switch (x) {
    case 0: return ConcreteClassA.class;
    case 1: return ConcreteClassB.class;
    }
    return null;
}

我跑了(得到)

This is ConcreteClassB

對於這種方法,

public Class<AbstractSuperClass> getConcreteClass(int x){
    switch( x ){
        case 0: return ConcreteClassA.class;
        case 1: return ConcreteClassB.class;
    }
}

簽名應該是

public Class<? extends AbstractSuperClass> getConcreteClass(int x)

這意味着返回值可以是AbstractSuperClass.class或其任何子類型。

嘗試這個:

public abstract class AbstractSuperClass {

    public abstract void someAbstractMethod();

    public static String getSomeText() { 
        return "This is AbstractSuperClass"; 
    };

    public Class<? extends AbstractSuperClass> getConcreteClass() {
        return this.getClass();
    }
}

實際上,您不需要int參數,因為子類的實例無需提示即可知道其類型。

我不確定它需要什么,但是您的代碼中有幾個問題。

  1. 您不能返回Class,因為您要返回擴展AbstractSuperClass的類。 因此,您必須通知編譯器並將其返回類型更改為Class
  2. 您不能直接從類中調用any(無關緊要的靜態方法或非靜態方法)。 您需要使用反射API,因此您的方法調用將如下所示:

    final class clazz = AbstractSuperClass.getConcreteClass(1); 對象結果= clazz.getMethod(“ getSomeText”)。invoke(clazz);

這就是您的完整代碼。

package com.mycompany.sandbox;

import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;


abstract class AbstractSuperClass{

    public abstract void someAbstractMethod();


    public static String getSomeText(){ 
        return "This is AbstractSuperClass"; 
    };

    public static Class<? extends AbstractSuperClass> getConcreteClass(int x){
        switch( x ){
            case 0: return ConcreteClassA.class;
            case 1: return ConcreteClassB.class;
        }
      return null;
    }
}


class ConcreteClassA extends AbstractSuperClass{
    public void someAbstractMethod(){
        // Do something
    }

    public static String getSomeText(){ 
        return "This is ConcreteClassA"; 
    };
}



class ConcreteClassB extends AbstractSuperClass{
    public void someAbstractMethod(){
        // Do something
    }

    public static String getSomeText(){ 
        return "This is ConcreteClassB"; 
    };
}




// one class needs to have a main() method
public class HelloWorld
{
  // arguments are passed using the text field below this editor
  public static void main(String args[])
  {
      try {
          final Class<? extends AbstractSuperClass> clazz = AbstractSuperClass.getConcreteClass(1);
          Object result = clazz.getMethod("getSomeText").invoke(clazz);
          System.out.println(Objects.toString(result, "<NULL>"));
      } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
          Logger.getLogger(HelloWorld.class.getName()).log(Level.SEVERE, null, ex);
      }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM