Scala Traits

原创转载请注明出处:http://agilestyle.iteye.com/blog/2334648

 

Scala中的trait,相当于Java中interface,支持多种继承,但是语法还是有些差异的。

使用trait关键字定义特征,将多个特征组合到一个类中,需要以extends关键字开头,然后使用with关键字添加额外的特征

package org.fool.scala.traits

trait Color

trait Texture

trait Hardness

class Fabric

class Cloth extends Fabric with Color with Texture with Hardness

class Paint extends Color with Texture with Hardness

object Materials extends App {
  new Fabric
  new Cloth
  new Paint
}

 

跟抽象类一样,特征中的域和方法可以有定义,也可以是抽象的

package org.fool.scala.traits

trait AllAbstract {
  def f(n: Int): Int

  val d: Double
}

trait PartialAbstract {
  def f(n: Int): Int

  val d: Double

  def g(s: String) = s"($s)"

  val j = 42
}

trait Concrete {
  def f(n: Int) = n * 11

  val d = 1.8
}

 

单独的特征是不能实例化的,因为它没有全功能的构造器。

/* None of these are legal -- traits
cannot be instantiated:
new AllAbstract
new PartialAbstract
new Concrete
*/

 

在组合特征来生成新类时,所有域和方法都必须有定义,否则Scala会强制要求该类必须包含abstract关键字

// Scala requires 'abstract' keyword:
abstract class Klass1 extends AllAbstract with PartialAbstract

/* Can't do this -- d and f are undefined:
new Klass1
*/

 

这些定义可以由新类提供,e.g. Klass2,或者通过其他特征实现,e.g. Klass3、Klass4、Klass5中的Concrete(抽象类中的方法也支持这种操作)

class Klass2 extends AllAbstract {
  def f(n: Int) = n * 12

  val d = 3.14
}

class Klass3 extends AllAbstract with Concrete

class Klass4 extends PartialAbstract with Concrete

class Klass5 extends AllAbstract with PartialAbstract with Concrete

new Klass2
new Klass3
new Klass4
new Klass5

 

特征可以被抽象类或具体类继承

trait FromAbstract extends Klass1

trait FromConcrete extends Klass2

 

特征不能有构造器参数,但可以有构造器体

trait Construction {
  println("Constructor body")
}

class Constructable extends Construction

new Constructable

Console Output


 

show an interesting trick: creating an instance of a class that you assemble at the site of creation. The resulting object has no type name. This technique creates a single instance of an object without creating a new named class just for that one usage.

val x = new AllAbstract with PartialAbstract with Concrete

 

特征可以继承其他特征

package org.fool.scala.traits

trait Base {
  def f = "f"
}

trait Derived1 extends Base {
  def g = "17"
}

trait Derived2 extends Derived1 {
  def h = "1.23"
}

class Derived3 extends Derived2

object TraitInheritance extends App {
  val d = new Derived3
  println(d.f)
  println(d.g)
  println(d.h)
}

Console Output


 

组合特征时,有可能会将具有相同签名(方法与类型的组合)的两个方法混合在一起。如果方法或域的签名产生冲突,那么需要人工解决这种冲突,e.g. 在object C中看到的那样(这里object起到快捷方式的作用,通过它可以创建类,然后创建该类的一个实例)

package org.fool.scala.traits

trait A {
  def f = 1.1

  def g = "A.g"

  val n = 7
}

trait B {
  def f = 2.2

  def g = "B.g"

  val n = 17
}

object C extends A with B {
  override def f = 3.3

  override def g = super[A].g + super[B].g

  override val n = 27
}

object TraitCollision extends App {
  println(C.f)
  println(C.g)
  println(C.n)
}

Console Output


 

特征域和方法即使还未被定义,也可以在计算中使用它们

package org.fool.scala.traits

trait Framework {
  val part1: Int

  def part2: Double

  // even without definitions:
  def templateMethod = part1 + part2
}

class Implementation extends Framework {
  override val part1 = 12

  override def part2 = 1.23
}

object FrameworkTest extends App {
  def operation(impl: Framework) = impl.templateMethod

  println(operation(new Implementation))
}

Console Output


 

参考资料:

Scala编程思想 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值