DarkMatter in Cyberspace
  • Home
  • Categories
  • Tags
  • Archives

Trait in Scala


早上研究了Scala的trait与abstract class的区别,大体有以下几点:

  • 抽象类代表一个独立的实体,trait代表一个具体的功能,不能独立存在;

  • 如果希望多个彼此无关的类复用一项相同的功能,把它用trait实现;

  • 一个类只能继承(使用 extensds 关键字)一个抽象类, 但可以mixin(使用 with 关键字)多个trait,可以同时使用, 例如下面实例中的 class D extends B with C;

  • 抽象类可以有类型参数(通过使用 type 关键字)和构造函数参数, trait只能有类型参数;

  • trait可以继承自(extends)其他trait;

  • trait可以继承自(extends)抽象类,例如下面的 trait C extends A;

  • 当无法确定使用trait还是抽象类时,优先使用trait;

实例代码1:

abstract class A {
  val message: String
}
class B extends A {
  val message = "I'm an instance of class B"
}
trait C extends A {
  def loudMessage = message.toUpperCase()
}
class D extends B with C
val d = new D
d.message  // I'm an instance of class B
d.loudMessage  // I'M AN INSTANCE OF CLASS B

mixin的栈特性(stackable):

trait A{
    def a = 1
}

trait X extends A{
    override def a = {
        println("X")
        super.a
    }
}

trait Y extends A{
    override def a = {
        println("Y")
        super.a
    }
}

scala> val xy = new AnyRef with X with Y
xy: java.lang.Object with X with Y = $anon$1@6e9b6a
scala> xy.a
Y
X
res0: Int = 1

scala> val yx = new AnyRef with Y with X
yx: java.lang.Object with Y with X = $anon$1@188c838
scala> yx.a
X
Y
res1: Int = 1

讨论

2013年在广州开发GODU时,曾经设计过这样的类结构: 接口 > 抽象类 > 多个具体实现类。 之所以要在接口和具体实现类之间插入一个抽象类层, 就是因为有一些通用的方法实现不能写在接口里,如果放在具体实现类里, 又会出现大量的冗余,但这样的3层结构,导致最上面的接口被架空,只能作为名义上的行为规范。 如果用Scala实现,就可以把通用功能放在trait里面实现, 各个具体实现类 MyConcreteClass1 extends MyInterface with MyTrait 就可以了。

参考:

  • https://stackoverflow.com/questions/1991042/what-is-the-advantage-of-using-abstract-classes-instead-of-traits

  • https://stackoverflow.com/questions/2005681/difference-between-abstract-class-and-trait

  • http://docs.scala-lang.org/tutorials/tour/mixin-class-composition.html.html



Published

Aug 10, 2017

Last Updated

Aug 10, 2017

Category

Tech

Tags

  • class 4
  • scala 20
  • trait 1

Contact

  • Powered by Pelican. Theme: Elegant by Talha Mansoor