【问题标题】:Generic Types - Accessing current class in superclass通用类型 - 访问超类中的当前类
【发布时间】:2015-10-21 08:43:58
【问题描述】:

我有两节课。我的第一个叫做“Manager”,依赖于我的第二个类“ManageAble”。这种依赖是通过一个泛型类型实现的,它是一个类参数,您可以在 Manager 的代码中看到:

public class ManageAble {

 private int id;
 private Manager<?> manager;

 protected ManageAble() {
 }

 @SuppressWarnings("unused")
 // used by reflection
 private final <T extends ManageAble> void construct(Manager<T> pManager,
        final Integer pID) {
    manager = pManager;
    id = pID;
 }

 @SuppressWarnings("unused")
 // used by reflection
 private final void deconstruct() {
    manager = null;
    id = -1;
 }

 protected boolean isAttatched() {
    return manager != null;
 }

 public final <T extends ManageAble> Manager<T> getManager() {
    if (manager != null) {
        try {
            @SuppressWarnings("unchecked")
            Manager<T> castedManager = (Manager<T>) manager;
            return castedManager;
        } catch (ClassCastException pCce) {
            // returns null
        }
    }
    return null;
 }

 public final int getID() {
    return id;
 }

 @Override
 public String toString() {
    return "[" + id + "] - " + manager;
 }
}

“Manager”类的“register”方法将在“ManageAble”类的构造函数中调用。但为此我需要弄清楚,如果我当前的对象是一个类的实例,它可以用作方法“register”中的参数“pType”。这是“ManagerAble”的代码:

public class Manager<Type extends ManageAble> {

 private final Map<Integer, Type> managed = new HashMap<Integer, Type>();
 private final Method construct = getManageAbleMethod("construct",
        new Class[] { Manager.class, Integer.class });
 private final Method deconstruct = getManageAbleMethod("deconstruct", null);

 public final boolean isManaging(final ManageAble pEntity) {
    if (pEntity != null) {
        return pEntity.equals(managed.get(pEntity.getID()));
    }
    return false;
 }

 public final boolean detatch(final ManageAble pEntity) {
    if (isManaging(pEntity)) {
        managed.remove(pEntity.getID());
        try {
            Object[] param = null;
            deconstruct.invoke(pEntity, param);
        } catch (IllegalAccessException | IllegalArgumentException
                | InvocationTargetException e) {
            // won't happen
        }
        return true;
    }
    return false;
 }

 public final synchronized boolean attatch(final Type pEntity) {
    if (pEntity != null)
        if (!isManaging(pEntity) && !pEntity.isAttatched()) {
            int id = getFreeID();
            managed.put(id, pEntity);
            try {
                construct.invoke(pEntity, new Object[] { this, id });
            } catch (IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException e) {
                // won't happen
            }
            return true;
        }
    return false;
 }

 private final int getFreeID() {
    int id = 0;
    Set<Integer> idsInUse = managed.keySet();
    while (idsInUse.contains(id))
        id++;
    return id;
 }

 private final Method getManageAbleMethod(final String pMethodName,
        final Class<?>[] pParam) {
    try {
        Method m = ManageAble.class.getDeclaredMethod(pMethodName, pParam);
        m.setAccessible(true);
        return m;
    } catch (NoSuchMethodException | SecurityException e) {
        return null;
    }
 }
}

如您所见,在我插入注释而不是泛型类型参数的地方,我不知道如何强制参数成为定义构造函数的类。

有什么方法可以访问当前类在其超类中的泛型类型?

感谢您的帮助:)

编辑:我将代码更新为到目前为止的内容。我通过丑陋的尝试/捕捉和反思或多或少地解决了我的问题......有更好的想法吗?

【问题讨论】:

  • (不确定我是否理解)你在找Manager&lt;ManageAble&gt;吗?
  • 没有。我不想在我的类“ManagerAble”中编写一个构造函数,它将当前类的管理器作为类型参数。因此,如果您直接使用 ManagerAble,则泛型类型应为 ManagerAble。如果您实例化任何子类,则泛型类型应为子类

标签: java generics superclass


【解决方案1】:

我认为为了满足您的要求,您的 ManageAble 类也应该是泛型的。像

public class ManageAble<T>  {

    private final int id;

    protected ManageAble(Manager<? super T> pManager) {
        id = pManager.register((T) this);
    }

    public final int getID() {
        return id;
    }

    @Override
    public String toString() {
        return "[" + id + "]";
    }

}

当然,Manager 会变成:

public class Manager<Type extends ManageAble<Type>> {
...

然后你可以像这样使用它:

class Foo extends ManageAble<Foo> {

    public Foo(Manager<? super Foo> pManager) {
        super(pManager);
    }
}    

Manager<Foo> mg = new Manager<>();
Foo f = new Foo(mg);

【讨论】:

  • 我仍然可以做 ManageAble ,它会破坏整个结构。我需要一些安全的东西,因为它将成为其他人的 api。你的演员也没有像我的那样被保存。我正在寻找一个安全的演员
  • @Basti :不,您不能直接使用它。因为您必须将 Manager 传递给它,并且必须为 class T extends ManageAble&lt;T&gt; 构造管理器,并且 String 不会(直接)扩展 ManageAble !所以你应该首先构建一个 ManageAble 扩展字符串。只需在 IDE 中尝试...
  • @Basti :我忘记了 Manager 类的声明行。请查看我的编辑。
  • 是的,我已经理解你的想法,但我正在寻找一种保存方法,你不能欺骗使用当前操作的类作为类型。我在我的一个旧项目中使用了您解决它的方式,但就我而言,这不是一个好的解决方案。还是谢谢你
  • @Basti:你靠自己:-)。我也使用这些构造,即使我更喜欢一个类依赖于另一个类,并且我避免交叉依赖。但是 AFAIK,你将无法欺骗它......如果你说没有满足什么要求,我可以加强解决方案。
猜你喜欢
  • 2021-05-24
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
相关资源
最近更新 更多