11-scala的内部类、抽象类型、复合类型和自类型

115 阅读1分钟

内部类

scala的内部类和Java存在差异。像Java这种语言,内部类很多时候就是为了区分命名上的差异;而scala中,却完全表示两种对象。举个例子:

package example

class AppleBasket {
  case class Apple(name: String, price: Float)

  private var apples: List[Apple] = Nil

  def addApple(apple: Apple) = apples = apple :: apples
}

object MyExample {

  def main(args: Array[String]): Unit = {
    val ab0 = new AppleBasket
    val ab1 = new AppleBasket

    val a0 = new ab0.Apple("a0", 1.1f)
    ab0.addApple(a0)
    // 这里直接报错,只有ab0才能添加a0
    // ab1.addApple(a0)
  }
}

对象的内部类是不能混合的。

抽象类型

直接给出代码实例,注意type的使用方式:

package example

abstract class Buffer[+T] {
  val element: T
}

abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
  def length = element.length
}

object MyExample {

  def newIntSeqBuffer(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = {
    new SeqBuffer[Int, Seq[Int]] {
      val element = List(e1, e2)
    }
  }

  def main(args: Array[String]): Unit = {
    val buf = newIntSeqBuffer(7, 8)
    println("length = " + buf.length)
    println("content = " + buf.element)
  }
}

复合类型

有时需要表明一个对象的类型是其他几种类型的子类型。举个例子:

package example

trait Fly {
  def fly(): Unit
}

trait Run {
  def run(): Unit
}

class Bird extends Fly with Run {
  override def fly() = println("Bird fly")

  override def run() = println("Bird run")
}

object MyExample {
  // 注意这里的with,表示复合类型
  def op(action: Fly with Run) {
    action.fly()
    action.run()
  }

  def main(args: Array[String]): Unit = {
    val bird = new Bird
    op(bird)
  }
}

代码输出:

Bird fly
Bird run

自类型

自类型用于声明一个特质必须混入其他特质,尽管该特质没有直接扩展其他特质。举个例子:

package example

trait Fly {
  val wingName: String
  def fly(): Unit
}

trait Run {
  this: Fly =>  // 自类型,这里表示可以使用Fly的特性了
  def showWingName() = println(s"My wing is $wingName")
  def run(): Unit
}

class Bird extends Fly with Run {
  override val wingName: String = "Bird-Wing"
  
  override def fly(): Unit = println("Bird fly")
  
  override def run(): Unit = println("Bird run")
}


object MyExample {

  def main(args: Array[String]): Unit = {
    val bird =  new Bird
    bird.showWingName()
  }
}