Scala中的结构类型调度
我试图更好地掌握结构类型调度。例如,假设我有一个iterable对象,它有一个Scala中的结构类型调度,scala,Scala,我试图更好地掌握结构类型调度。例如,假设我有一个iterable对象,它有一个summary方法来计算平均值。因此o.summary()给出了列表的平均值。我可能想使用结构类型分派来启用summary(o) 关于o.summary()与summary(o),是否有一套最佳实践 如果我有一个方法summary(o:ObjectType)和summary(o:{def summary:Double}),scala如何解析summary(o) 结构类型分派与多方法或泛型函数有何不同 Michael G
summary
方法来计算平均值。因此o.summary()
给出了列表的平均值。我可能想使用结构类型分派来启用summary(o)
o.summary()
与summary(o)
,是否有一套最佳实践summary(o:ObjectType)
和summary(o:{def summary:Double}),scala如何解析summary(o)
结构类型是Scala版本的“响应”式编程,在许多动态语言中都可以看到。很像
def sayName ( x : { def name:String }){
println(x.name)
}
然后,任何名为name的方法不带参数且返回字符串的对象都可以传递给sayName:
case class Person(name:String)
val dean = Person("Dean")
sayName(dean) // Dean
--
1。在您的示例中,我不会使用summary(o)
版本,因为这不是一种非常面向对象的编程风格。调用o.summary
时(可以去掉括号,因为它没有副作用),您需要o
的summary
属性。调用summary(o)
时,将o
传递给计算o
的摘要的方法。我认为第一种方法更好:)
我没有太多使用结构类型分派,但我认为它最适合(在大型系统中)只因为一个方法需要定义了某个方法的类型而必须编写接口的情况。有时,创建该接口并强制客户机实现它可能会很尴尬。有时,您希望使用另一个API中定义的客户机,该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。我想要任何类型的东西;B我想要某种类型的东西,它是a的一个子类型;C我要一个B的超型;D我将采用隐式转换为C类型的方法。所有这些都比“我想要一个具有正确签名的方法foo
的类型”严格得多。此外,结构类型分派确实使用反射,因为它们是通过类型擦除实现的
我对多方法知之甚少,但看看下面的例子,Scala中的多方法似乎可以通过模式匹配来实现。例如:
def collide(a: Collider, b: Collider) = (a, b) match {
case (asteroid: Asteroid, spaceship: Spaceship) => // ...
case (asteroid1: Asteroid, asteroid2: Asteroid) => // ...
...
同样,您可以使用结构类型dispatch-defclide(a:{def processCollision()})
,但这取决于设计决策(在本例中,我将创建一个接口)
--Flaviu-Cipcigan
结构数据类型并不是那么有用。这并不是说它们毫无用处,但它们绝对是一个利基的东西
例如,您可能想为某个东西的“大小”
”编写一个通用测试用例。您可以这样做:
def hasSize(o: { def size: Int }, s: Int): Boolean = {
o.size == s
}
然后,这可以用于实现“size”方法的任何对象,无论其类层次结构如何
现在,它们不是结构类型调度。它们与分派无关,而是与类型定义有关
Scala始终是一种面向对象的语言。必须对对象调用方法。函数调用实际上是“
apply
”方法调用。像“println
”这样的东西只是导入范围的对象的成员。我想你问过Scala对结构类型的调用做了什么。它使用反射。例如,考虑
def repeat(x: { def quack(): Unit }, n: Int) {
for (i <- 1 to n) x.quack()
}
def repeat(x:{def-quack():Unit},n:Int){
对于(谢谢,这很有帮助。在最后一点上,我相信多方法会避免使用case/switch类型语句,因为使用collide的所有类型都必须由api设计器知道。