Java或Scala:在运行时创建新类型
如何在运行时定义新类型?我有一个工厂方法,需要创建此的新实例。键入带有标记接口的Java或Scala:在运行时创建新类型,java,scala,reflection,Java,Scala,Reflection,如何在运行时定义新类型?我有一个工厂方法,需要创建此的新实例。键入带有标记接口的。在编译时没有混合标记接口。我需要找到一种在运行时执行此操作的方法 我使用的是Scala,但我认为答案足够笼统,足以涵盖Java和Scala trait Fruit { def eat: this.type with Eaten = { getClass.getConstructors()(0).newInstance(Array()).asInstanceOf[this.type];
。在编译时没有混合标记接口。我需要找到一种在运行时执行此操作的方法
我使用的是Scala,但我认为答案足够笼统,足以涵盖Java和Scala
trait Fruit {
def eat: this.type with Eaten = {
getClass.getConstructors()(0).newInstance(Array()).asInstanceOf[this.type];
// somehow this needs to return a new instance of this.type with the Eaten trait
// note that "Apple with Eaten" is not a type that exists at compile-time
}
}
trait Eaten // marker interface
class Apple extends Fruit
val apple1 = new Apple
val apple2 = a.eat // should return a new Apple with Eaten instance
def eater(eaten: Eaten) = ... // this function only accepts Eaten fruit
eater(apple1) // wont compile!
eater(apple2) // will compile!
我不太确定你想解决什么样的问题,但也许你可以用类型构造函数之类的东西来代替实现一个特性,所以eat变成了
class Eaten[T]
class Fruit[F : Manifest <: Fruit[F]] {
def eat: F with Eaten = {
val clazz = manifest[F].erasure
val result = // do your bytecode manipulations here
result.asInstanceOf[F with Eaten]
}
}
和苹果。吃返回一个
Eaten[Apple]
JDK6将允许您编译实际的Java代码。看
或者(特别是如果您希望创建一个类来实现接口),您应该签出:,这将允许您执行以下操作:
InvocationHandler handler = new MyInvocationHandler(...);
Class proxyClass = Proxy.getProxyClass(
Foo.class.getClassLoader(), new Class[] { Foo.class });
Foo f = (Foo) proxyClass.
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
请注意,这样做也非常简单。在Scala中,有一个叫做的东西可以使用。但是在Java中没有等价物
您的代码看起来像:
implicit def fruit2eaten(fruit: Fruit) = // some way of creating an Eaten from a fruit here.
据我所知,scala不是一种动态语言,它更多的是一种函数式语言。现在在groovy中,它是一种动态语言,您可以在字符串或文本文件中定义一个类,并在运行时对其进行求值,但我认为在scala中不可能实现这些功能
编辑:某些动态功能是这是不可能的。当然,在运行时创建新类有多种方法:只需使用任何操作即可。但是this.type
不是“this
的类”,而是this
的单例类型(并且在Scala类型签名中无法表示“this的类)!所以
当然,如果Apple
没有扩展eat
,它就不会编译,不管你在方法内部做什么。通常的解决方法是
class Eaten[T]
class Fruit[F : Manifest <: Fruit[F]] {
def eat: F with Eaten = {
val clazz = manifest[F].erasure
val result = // do your bytecode manipulations here
result.asInstanceOf[F with Eaten]
}
}
显然,我正在尝试实现一个吃水果的模拟实际上,我已经创建了一个DSL,用于使用Scala类型系统描述文档模式。文档结构使用匿名声明类的树来描述。树是一个不可变的数据结构,但在某些用例中,我需要树上的节点来承载状态。我希望通过混合使用新类型来表示这种状态,这样就可以保证这种状态的依赖关系在编译时存在。另见这个问题