-- 1. 在您的示例中,我不会使用summary(o) 版本,因为这不是一种非常面向对象的编程风格。当调用o.summary 时(你可以去掉括号,因为它没有副作用),你要求o 的summary 属性。当调用summary(o) 时,您将o 传递给计算o 的摘要的方法。我相信第一种方法更好:)。
我没有过多使用结构类型分派,但我认为它最适合(在大型系统中)仅因为一个方法想要一个定义了某个方法的类型而必须编写接口的情况.有时创建该接口并强制客户端实现它可能会很尴尬。有时您想使用在另一个 API 中定义的客户端,该客户端符合您的接口但没有显式实现它。因此,在我看来,结构类型分派是隐式制作适配器模式的好方法(节省样板文件,耶!)。
-- 2. 显然,如果您调用 summary(o) 并且 o 属于 ObjectType,则 summary(o: ObjectType) 会被调用(这确实有意义)。如果您调用summary(bar),其中bar 不属于ObjectType,可能会发生两件事。如果bar 具有正确签名和名称的summary() 方法,则调用编译,否则,调用不会编译。
例子:
scala> case class ObjectType(summary: Double)
defined class ObjectType
scala> val o = ObjectType(1.2)
o: ObjectType = ObjectType(1.2)
scala> object Test {
| def summary(o: ObjectType) { println("1") }
| def summary(o: { def summary: Double}) { println("2")}
| }
defined module Test
scala> Test.summary(o)
1
很遗憾,由于类型擦除,以下内容无法编译:
scala> object Test{
| def foo(a: {def a: Int}) { println("A") }
| def foo(b: {def b: Int}) { println("B") }
| }
:6: error: double definition:
method foo:(AnyRef{def b(): Int})Unit and
method foo:(AnyRef{def a(): Int})Unit at line 5
have same type after erasure: (java.lang.Object)Unit
def foo(b: {def b: Int}) { println("B") }
-- 3. 从某种意义上说,结构类型的调度比泛型方法更动态,并且服务于不同的目的。在通用方法中,您可以说:我想要任何类型的东西;湾。我想要某种类型的东西,它是 A 的子类型; C。我将采用 B 的超类型; d。我将采用隐式转换为 C 类型的东西。所有这些都比“我想要一个具有正确签名的方法 foo 的类型”要严格得多。此外,结构类型调度确实使用反射,因为它们是通过类型擦除实现的。
我对multimethods了解不多,但是看wikipedia article,似乎Scala中的multimethods可以使用模式匹配来实现。示例:
def collide(a: Collider, b: Collider) = (a, b) match {
case (asteroid: Asteroid, spaceship: Spaceship) => // ...
case (asteroid1: Asteroid, asteroid2: Asteroid) => // ...
...
同样,您可以使用结构类型调度 - def collide(a: {def processCollision()}),但这取决于设计决策(我将在此示例中创建一个接口)。
-- Flaviu Cipcigan