Scala:涉及匿名子类、回调和类型参数的棘手案例
我甚至不知道如何描述我在做什么,除了举个例子:Scala:涉及匿名子类、回调和类型参数的棘手案例,scala,Scala,我甚至不知道如何描述我在做什么,除了举个例子: class Node abstract class App { def schema: Node } def bind(app: App, f: Node => Node) { f(app.schema) } val app = new App { val schema = new Node { val child = new Node } } bind(app, _.child) 这
class Node
abstract class App {
def schema: Node
}
def bind(app: App, f: Node => Node) {
f(app.schema)
}
val app = new App {
val schema = new Node {
val child = new Node
}
}
bind(app, _.child)
这是不可编译的。我从bind
调用中获取:错误:值子节点不是此节点的成员
我不知道如何解决这个问题,但我认为这可能涉及到参数化类型的使用。我需要f
的参数类型是分配给schema
的实际节点
子类的参数类型
编辑:我不能明确命名我的节点
子类型,因为在现实生活中,我有静态定义的节点
的整棵树,命名它们是不切实际的。节点
没有方法子节点
,因此类应用程序必须保留封闭节点的参数:
abstract class App[N <: Node] {
def schema: N
}
最后,您可以将bind
编写为:
def bind[N <: Node](app: App[N], f: N => N) = {
f(app.schema)
}
val app = new App[ParentNode] {
val schema = new ParentNode
}
def绑定[N]{
f(应用程序架构)
}
val app=新应用程序[父节点]{
val schema=newparentnode
}
bind
具有签名appx(Node=>Node)=>Node
\.child
在此上下文中表示{n:Node=>n.child}
并且Node未定义child。这就是错误消息所告诉的
在您的特定情况下,您可以期望它能够工作,因为您知道bind的函数参数应用于app参数的schema节点。但是,您应该告诉编译器几乎相同的内容。这将迫使您公开一些实现细节
首先,您的函数可能没有节点参数,而是更精确的参数。您可以有一个泛型参数:
def bind[N <: Node](app: App, f: N => Node)
最后,您必须使应用程序的类型更加明确,至少是这样
class NodeOfApp{def child: Node}
val app = new App[NodeOfApp]{...}
你可以这样做:
def bind[T](app: App{val schema: T}, f: T => Node) { f(app.schema) }
bind[{val child: Node}](app, _.child)
我想这对于您试图实现的目标来说仍然过于冗长。Thank you@paradigmatic。我应该澄清一下,我需要保持匿名节点子类型的使用。这是我正在开发的内部DSL的代表,节点树要易于实现,并且不需要显式命名子类。T谢谢。请参阅我对@paradigmatic的评论。我无法明确命名我的节点子类型,因为在现实生活中,我有整个静态定义节点树,命名它们并不实际。谢谢,但这需要在参数类型定义中重复整个模式。在现实生活中,模式是一个连接节点的大型图实例。
class NodeOfApp{def child: Node}
val app = new App[NodeOfApp]{...}
def bind[T](app: App{val schema: T}, f: T => Node) { f(app.schema) }
bind[{val child: Node}](app, _.child)