我在Scala中有以下课程:
class A {
def doSomething() = ???
def doOtherThing() = ???
}
class B {
val a: A
// need to enhance the class with both two functions doSomething() and doOtherThing() that delegates to A
// def doSomething() = a.toDomething()
// def doOtherThing() = a.doOtherThing()
}
我需要一种在编译时增强类B的方法,该类具有与A相同的函数签名,当在B上调用时,该函数签名简单地委托给A。
在Scala中有一种不错的方法吗?
谢谢。
答案 0 :(得分:6)
在Dotty(以及未来的Scala 3)中,其简称为now available
class B {
val a: A
export a
}
或export a.{doSomething, doOtherThing}
。
不幸的是,对于Scala 2,没有内置的解决方案。正如蒂姆所说,您可以做一个,但是您需要确定愿意花费多少努力以及到底要支持什么。
答案 1 :(得分:3)
可以通过为每个函数创建别名来避免重复函数签名:
val doSomething = a.doSomething _
val doOtherthing = a.doOtherThing _
但是这些现在是函数值而不是方法,根据使用情况,它们可能相关也可能不相关。
也许可以使用trait
或基于宏的解决方案,但这取决于使用委派的原因的详细信息。
答案 2 :(得分:3)
隐式转换可以像这样用于委派
object Hello extends App {
class A {
def doSomething() = "A.doSomething"
def doOtherThing() = "A.doOtherThing"
}
class B {
val a: A = new A
}
implicit def delegateToA(b: B): A = b.a
val b = new B
b.doSomething() // A.doSomething
}
答案 3 :(得分:0)
这个宏 delegate-macro 可能正是您要找的。它的目标是自动实现委托/代理模式,因此在您的示例中,您的类 B
必须扩展类 A
。
它是针对 2.11
、2.12
和 2.13
进行交叉编译的。对于 2.11
和 2.12
,您必须使用宏天堂编译插件才能使其工作。对于 2.13
,您需要改用标志 -Ymacro-annotations
。
像这样使用它:
trait Connection {
def method1(a: String): String
def method2(a: String): String
// 96 other abstract methods
def method100(a: String): String
}
@Delegate
class MyConnection(delegatee: Connection) extends Connection {
def method10(a: String): String = "Only method I want to implement manually"
}
// The source code above would be equivalent, after the macro expansion, to the code below
class MyConnection(delegatee: Connection) extends Connection {
def method1(a: String): String = delegatee.method1(a)
def method2(a: String): String = delegatee.method2(a)
def method10(a: String): String = "Only method I need to implement manually"
// 96 other methods that are proxied to the dependency delegatee
def method100(a: String): String = delegatee.method100(a)
}
它应该适用于大多数场景,包括涉及类型参数和多个参数列表时。
免责声明:我是宏的创建者。