我是 Scala 新手。
我有一个 A 类
,它扩展了
C 类
。我还有一个 B 类
,它也扩展
C 类
我希望 A->B
类型的函数对象也扩展 C
(以及其他派生类型,例如 A->(A->B)
)。但我在“Scala 编程”中读到了以下内容:
A function literal is compiled into a class that when instantiated at runtime is a function value.
是否有某种方法可以自动让 A->B
extend
C
,而不需要手动创建一个代表功能?
最佳答案
Scala 中的函数是通过 FunctionN
特征建模的。例如,简单的一输入一输出函数都是以下特征的实例:
trait Function1[-T1, +R] extends AnyRef
所以你问的是“如何使 Function
的实例也成为 C
的子类”。这无法通过标准子类型/继承来实现,因为显然我们无法修改 Function1
特征以使其扩展您的自定义类 C
。当然,我们可以按照您的建议创建一个新类来表示该函数,但这只会让我们到目前为止,并且实现起来并不容易,更不用说您想要用作 C 的任何函数了code> 必须首先转换为您的伪函数特征,这将使事情变得可怕。
但是,我们可以做的是创建一个类型类,其中包含 A -> B
等的实现。
我们以下面的代码为例:
trait A
trait B
trait C[T]
object C {
implicit val fa = new C[A] {}
implicit val fb = new C[B] {}
implicit val fab = new C[Function1[A, B]] {}
}
object Test extends scala.App {
val f: A => B = (a: A) => new B {}
def someMethod[Something: C](s: Something) = {
// uses "s", for example:
println(s)
}
someMethod(f) // Test$$$Lambda$6/1744347043@dfd3711
}
你还没有具体说明让 A -> B 扩展 C 的动机,但显然你希望能够将 A、B 和 A -> B 放在“同一把伞”下,因为你有,比如说,某种方法(称为 someMethod
),它采用 C
,因此通过继承,您可以向其传递 A、B 或 A -> B 类型的值。
使用类型类,您可以实现相同的目标,并具有一些额外的优点,例如有一天,在不更改现有代码的情况下将 D
添加到系列中(您只需要在范围内的某个位置实现类型 C[D]
的隐式值)。
因此,不是让 someMethod
获取 C
的实例,而是简单地获取某种类型的东西(让我们称之为 s
)(让我们称之为它 Something
),约束条件是 C[Something]
必须存在。如果您传递 C 实例不存在的内容,您将收到错误:
trait NotC
someMethod(new NotC {})
// Error: could not find implicit value for evidence parameter of type C[NotC]
您实现了同样的目标 - 您有一个 C
家族,其成员为 A
、B
和 A => B
,但是你可以解决子类型问题。
关于scala - 如何在 Scala 中扩展函数类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48263968/