scala之旅-核心语言特性【特性】(七)

特性用于类之间的接口和属性共享。它们跟java8中的接口有些类似【注:这里官方说的很准确,类似于java8的接口,而不是java7及之前的接口。因为trait同时可以声明抽象方法,也可以实现抽象方法。相当于是java接口的default的一个推广使用。】。类和伴生对象可以继承特性,但是特性不能被实例化,因此也不会有构造参数。

定义特性

一个最简单的特性可以用一个 trait 关键字和一个标志符表示:

trait HairColor

特性在泛型和抽象方法中尤为凸显优势

trait Iterator[A] {
  def hasNext: Boolean
  def next(): A
}

继承特性 Iterator[A] 需要一个类型A ,并且实现hasNext和next 方法

使用特性

使用关键字 extends 来继承一个特性。然后实现特性的任何抽象成员时需要加上 override 关键字

trait Iterator[A] {
  def hasNext: Boolean
  def next(): A
}

class IntIterator(to: Int) extends Iterator[Int] {
  private var current = 0
  override def hasNext: Boolean = current < to
  override def next(): Int = {
    if (hasNext) {
      val t = current
      current += 1
      t
    } else 0
  }
}


val iterator = new IntIterator(10)
iterator.next()  // returns 0
iterator.next()  // returns 1

这里的 IntIterator 使用一个 形参to 作为一个上边界, 继承Iterator[Int] 意味着使用 next 方法时必须返回一个Int 类型

子类型化

当需要一个给定的特性时,可以用这个特性的子类型代替。

import scala.collection.mutable.ArrayBuffer

trait Pet {
  val name: String
}

class Cat(val name: String) extends Pet
class Dog(val name: String) extends Pet

val dog = new Dog("Harry")
val cat = new Cat("Sally")

val animals = ArrayBuffer.empty[Pet]
animals.append(dog)
animals.append(cat)
animals.foreach(pet => println(pet.name))  // Prints Harry Sally

特性 Pet 有一个抽象属性name, Cat和Dog 通过结构体具体地实现了。 在最后一行,我们调用 pet.name之前,所有子类型必须实现特性 Pet.

 

posted @ 2020-10-23 10:00  周周周文阳  阅读(97)  评论(0编辑  收藏  举报