1、特征
Traits用于在类之间共享接口和字段。它们类似于Java 8的接口。类和对象可以扩展特征,但是特征不能被实例化,因此没有参数。
- 定义一个特征
最小特征只是关键字trait
和标识符:
trait Color
特征作为泛型类型和抽象方法特别有用。
trait Iterator[A] { def hasNext: Boolean def next(): A }
扩展(与Java中的实现类似)trait 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
作为上限。这extends 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(name="Harry") val cat = new Cat(name="Sally") val animals = ArrayBuffer.empty[Pet] animals.append(dog) animals.append(cat) animals.foreach(pet => println(pet.name))
trait Pet
有一个抽象字段name
,由Cat和Dog在其构造函数中实现。在最后一行,我们调用pet.name
哪个必须在特征的任何子类型中实现Pet
。
2、正则表达式
正则表达式是可用于在数据中查找模式(或缺少模式)的字符串。可以使用该.r
方法将任何字符串转换为正则表达式。
import scala.util.matching.Regex val numberPattern: Regex = "[0-9]".r numberPattern.findFirstMatchIn("awesomepassword11") match { case Some(_) => println("Password OK") case None => println("Password must contain a number") }
结果如下:
在上面的例子中,numberPattern
是一个Regex
(正则表达式),用它来确保密码包含一个数字。
3、提取器对象
提取器对象是具有unapply方法 的对象,虽然apply方法就像一个构造函数,接受参数并创建一个对象,但是unapply接受一个参数并试图回馈参数,通常用于模式匹配和部分功能。
import scala.util.Random object CustomerID { def apply(name:String) = s"$name--${Random.nextLong}" def unapply( customerID:String): Option[String] ={ val stringArray:Array[String]=customerID.split("--") if(stringArray.tail.nonEmpty) Some(stringArray.head) else None } def main(args: Array[String]): Unit = { val customer1ID = CustomerID("harry--aaaaaa--jurry") customer1ID match { case CustomerID(name) => println(name) case _ => println("Could not extract a CustomerID") } } }
该apply
方法CustomerID
从创建一个字符串name,
unapply
做反拿到name
回来。当我们调用时CustomerID("
harry--aaaaaa--jurry")
,这是调用的简写语法CustomerID.apply("harry--aaaaaa--jurry")
。当我们打电话时case CustomerID(name) => println(name)
,我们正在调用unapply方法。