英文:
Function with generic type as member variable
问题
我有一个将 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
的语法是不正确的。有没有办法保持 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);
}
}
这可以工作(并且显然通过不变式是正确的),但由于需要强制转换,有点丑陋。
英文:
I have a function which maps a class
object to an instance of this class.
Basically:
Function<Class<T>, T> fun;
I can define this function within a method but when trying to put this in a member variable, the compiler complains because the type T
is unknown.
So, T
is not specific to the enclosing object. It might differ from call to call. What is the correct syntax to define such a function on class level?
EDIT
I would like to clarify. I have class A
public class A {
public <T> T get(Class<T> clazz) {...}
}
Now, I want to hand a pointer to that function to class B
like this:
public class B {
<T> Function<Class<T>, T> fun;
public <T> T get(Class<T> clazz) {
return fun.apply(clazz);
}
}
However, the Syntax for <T> Function<Class<T>, T> fun
is incorrect. Is there a way to keep the information, that fun will always retain the type T
?
My current solution is
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);
}
}
This works (and is obviously correct via invariant) but kinda ugly because of the required cast.
答案1
得分: 3
在Java(以及JVM)中,值不具有多态性,方法具有多态性。
因此,正确的方法是用一个方法来定义它:
<T> Function<Class<T>, T> fun();
关于编辑部分。
现在,我想将一个指向该函数的指针传递给类
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
这样编写setter。其签名应该是类似以下形式:
public void setFun(Function<Class<T>, T> fun); // 伪代码
而不是:
public <T> void setFun(Function<Class<T>, T> fun);
<T> Function<Class<T>, T>
被称为rank-N类型,在Java中不存在。
或者,你可以用一个类(接口)来封装多态的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);
}
}
英文:
In Java (and JVM) values are not polymorphic, methods are.
So correct is to define it with a method
<T> Function<Class<T>, T> fun();
https://stackoverflow.com/questions/34886128/polymorphic-values-in-java
Regarding EDIT.
> Now, I want to hand a pointer to that function to class B
like this:
>
> public class B {
> <T> Function<Class<T>, T> fun;
>
> public <T> T get(Class<T> clazz) {
> return fun.apply(clazz);
> }
> }
Once again, a value (including a field) can't be polymorphic, method can.
-
So you can make
fun
a methodpublic abstract class B { abstract <T> Function<Class<T>, T> fun(); public <T> T get(Class<T> clazz) { return this.<T>fun().apply(clazz); } }
You can't write setter like
setFun
. Its signature should be something likepublic void setFun(<T> Function<Class<T>, T> fun); // pseudocode
rather than
public <T> void setFun(Function<Class<T>, T> fun);
<T> Function<Class<T>, T>
is called rank-N type and it's absent in Javahttps://stackoverflow.com/questions/12031878/what-is-the-purpose-of-rank2types
-
Alternatively, you can wrap polymorphic
fun
with a class (interface)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
looks like yourA
so maybe you wantpublic class B { A a; public void setA(A a) { this.a = a; } public <T> T get(Class<T> clazz) { return a.get(clazz); } }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论