Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java或Scala:在运行时创建新类型_Java_Scala_Reflection - Fatal编程技术网

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类型系统描述文档模式。文档结构使用匿名声明类的树来描述。树是一个不可变的数据结构,但在某些用例中,我需要树上的节点来承载状态。我希望通过混合使用新类型来表示这种状态,这样就可以保证这种状态的依赖关系在编译时存在。另见这个问题