具有泛型类型的函数作为成员变量

时间:2020-09-15 13:14:15

标签: java generics

我有一个将class对象映射到此类的实例的函数。 基本上:

 Function<Class<T>, T> fun;

我可以在方法中定义此函数,但是当尝试将其放入成员变量时,编译器会抱怨,因为类型T是未知的。

因此,T并非特定于封闭对象。每次通话可能会有所不同。在类级别定义此类功能的正确语法是什么?

编辑

我想澄清一下。我上了A

public class A {
  public <T> T get(Class<T> clazz) {...}
}

现在,我想像这样将指向该函数的指针传递给类B

public class B {
  <T> Function<Class<T>, T> fun;
  
  public <T> T get(Class<T> clazz) {
    return fun.apply(clazz);
  }
}

但是,<T> Function<Class<T>, T> fun的语法不正确。有没有一种方法可以保留信息,这种乐趣将始终保留类型T

我当前的解决方案是

public class B {
  Function<Class<?>, ?> fun;

  public <T> void setFun(Function<Class<T>, T> fun) {
    this.fun = fun;
  }

  public <T> T get(Class<T> clazz) {
    return (T) fun.apply(clazz);
  }
}

这有效(并且通过不变式显然是正确的),但由于需要强制转换,因此有点难看。

1 个答案:

答案 0 :(得分:3)

在Java(和JVM)中,值不是多态的,方法是。

所以正确的方法是使用它来定义

<T> Function<Class<T>, T> fun();

Polymorphic values in Java


关于编辑

现在,我想像这样将指向该函数的指针传递给类B

public class B {
  <T> Function<Class<T>, T> fun;
 
  public <T> T get(Class<T> clazz) {
    return fun.apply(clazz);
  }
}

再一次,值(包括字段)不能是多态的,方法可以。

  • 因此您可以将fun用作方法

     public abstract class B {
        abstract <T> Function<Class<T>, T> fun();
    
        public <T> T get(Class<T> clazz) {
            return this.<T>fun().apply(clazz);
        }
     }
    

    您不能像setFun那样写二传手。它的签名应该类似于

     public void setFun(<T> Function<Class<T>, T> fun); // pseudocode
    

    而不是

     public <T> void setFun(Function<Class<T>, T> fun);
    

    <T> Function<Class<T>, T>被称为N列类型,在Java中不存在

    What is the purpose of Rank2Types?

    https://wiki.haskell.org/Rank-N_types

  • 或者,您可以将多态fun与类(接口)包装起来

    public interface PolyFunction {
        <T> T apply(Class<T> clazz);
    }
    
    public class B {
        PolyFunction fun;
    
        public void setFun(PolyFunction fun) {
            this.fun = fun;
        }
    
        public <T> T get(Class<T> clazz) {
            return fun.apply(clazz);
        }
    }
    

    PolyFunction看起来像您的A,所以也许您想要

    public class B {
        A a;
    
        public void setA(A a) {
            this.a = a;
        }
    
        public <T> T get(Class<T> clazz) {
            return a.get(clazz);
        }
    }
    
相关问题