我是Scala的新手。 我有一个Class A
,extends
Class C
.我还有一个Class B
,也extends
Class C
我希望A->B
类型的函数对象也扩展C
(以及其他派生类型,例如A->(A->B)
)。但我在"Programming in scala"中读到:
函数文本被编译成一个类,当在运行时实例化时 是一个函数值。
有没有办法自动让A->B
extend
C
,而不是手动创建一个代表函数的新类?
Scala 中的函数是通过FunctionN
特征建模的。例如,简单的一输入一输出函数都是以下特征的实例:
trait Function1[-T1, +R] extends AnyRef
所以你要问的是"我怎样才能使Function
的实例也成为C
的子类"。这通过标准子类型/继承是不可行的,因为显然我们无法修改Function1
特征以使其扩展您的自定义类C
。当然,我们可以按照您的建议创建一个新类来表示函数,但这只会让我们走这么远,而且实现起来并不容易,更不用说任何你想用作C
的函数都必须首先转换为你的伪函数特征,这会让事情变得可怕。
然而,我们可以做的是创建一个类型类,然后包含一个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 的值。
使用typeclass,您可以实现相同的目标,但具有一些额外的优势,例如,有一天可以在不更改现有代码的情况下将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
,但你绕过子类型问题。