在对象后面有一个特征有什么好处?

时间:2016-01-15 04:49:34

标签: scala

在Scala 2.11标准库中,我们看到:

object StdIn extends StdIn

它带来了什么好处?没有其他类扩展这个特性。是否在函数调用中传递特征?单身对象有什么需要?

2 个答案:

答案 0 :(得分:8)

它被称为selfless trait pattern

  

您只需为特征本身混合的特征提供伴随对象即可实现无私特质模式。

trait Friendly {
  def greet() { println("hi there") }
}

object Friendly extends Friendly
  

此示例中的Trait Friendly有一种方法,问候。它还有一个名为Friendly的伴侣对象,它混合了特质友好。鉴于这种友好的设计,这个库的客户端程序员可以通过组合混合访问Friendly的服务,这样(友好的导入和使用以粗体显示):

object MixinExample extends Application with Friendly {
  greet()
}
  

或者通过导入友好伴侣对象的成员,如下所示:

import Friendly._

object ImportExample extends Application {
  greet()
}

答案 1 :(得分:3)

首先,拥有一个扩展特征的对象并不会限制我们创建更多的特征实例。在假设的情况下,可能有另一个版本/实现超过StdIn,我们可以声明以前的对象是过时的,保持相同的接口。但是,根据scaladocStdIn的情况并非如此:

/** private[scala] because this is not functionality we should be providing
 *  in the standard library, at least not in this idiosyncractic form.
 *  Factored into trait because it is better code structure regardless.
 */
private[scala] trait StdIn {

特征定义对象的类型和接口。这对于引用该类型很有用。考虑没有特质的情况,使用时会很尴尬和限制:

scala> object A { val id = 1 }
defined object A

scala> def f(v: A.type) = v.id
f: (v: A.type)Int

scala> f(A)
res1: Int = 1

scala> def f(v: A) = v.id
<console>:10: error: not found: type A
       def f(v: A) = v.id

不得不求助于结构化打字:

scala> def g(v: { def id: Int }) = v.id
g: (v: AnyRef{def id: Int})Int

scala> object B { val id = 2 }
defined object B

scala> g(B)
res5: Int = 2

scala> g(A)
res6: Int = 1

scala> f(B)
<console>:17: error: type mismatch;
 found   : B.type
 required: A.type
       f(B)
         ^

但是,我们无法使用StdIn特征,因为它是私有的:

scala> import scala.io._
import scala.io._

scala> val b: StdIn = ???
<console>:13: error: trait StdIn in package io cannot be accessed in package io
       val b: StdIn = ???
              ^

因此,您的问题非常合理,我看到的唯一好处是代码清晰度更高:抽象实现与实例/范围管理是分开的。