目录
字符串插值
- 在字符串的前面放一个s,在想让Scala插值的标识符之前放置一个$
- 任何以$为先导的标识符都会被转换成字符串
- 将表达式置于${}之间来计算和转换该表达式
case class Sky(color: String)
object Interpolation {
def i(s: String, n: Int, d: Double): String = s"first: $s, second: $n, third: $d"
def f(n: Int): Int = {n * 2}
def main(args: Array[String]): Unit ={
println(i("hello", 9, 89.0))
// 将表达式置于${}之间来计算和转换该表达式
println(s"the result of f(7) is: ${f(7)}")
println(s"""${new Sky("bule")}""")
}
}
输出:
first: hello, second: 9, third: 89.0
the result of f(7) is: 14
Sky(bule)
Vectors
创建Vector对象时,没有使用new关键字,事实上,我们无法用new关键字来创建Vector对象,Scala使用圆括号在序列中进行索引,Vecotr可以存放不同类型的数据
val v4 = Vector(2, 9.0, 'i', "p")
println("v4_0: " + v4(0))
val v2 = Vector()
//println("v2 head " + v2.head) //报错 empty.head
//println("v2 tail " + v2.tail) //报错 empty.tail
val v3 = Vector(1)
println("v3 head " + v3.head)
println("v3 tail " + v3.tail) //v3 tail Vector()
枚举类
Scala 没有从语言层面上支持枚举,需要利用继承的方式实现枚举,继承的是Enumeration抽象类。然后通过内部对象Value来赋值每一个枚举的值,创建object不会以创建class的方式创建新类型,若我们想要将其当作类型处理,必须使用type关键字,声明枚举对外暴露的变量类型
object Level extends Enumeration{
type Level = Value // 声明枚举对外暴露的变量类型
val Overflow, High, Medium, Low, Empty = Value // protected final def Value Scala.Enumeration
}
import Level._
object EunmClass {
// 要type Level = Value和import Level._一下,否则Level无法识别,Error: not found: type Level
// 没有type Level = Value,依旧可以使用Overflow等
def checkLevel(level: Level) = level match{
case Overflow => ">>> Overflow"
case other => s"Level $level"
}
def main(args: Array[String]): Unit ={
// 没有type Level = Value下面是不会报错的
Level.Overflow
println(Level.maxId)
val one = {for(n <- Range(0, Level.maxId)) yield (n, Level(n))}
println(one) // Vector((0,Overflow), (1,High), (2,Medium), (3,Low), (4,Empty))
val two = for(level <- Level.values) yield level
println(two) // Level.ValueSet(Overflow, High, Medium, Low, Empty)
println(two.toIndexedSeq) // Vector(Overflow, High, Medium, Low, Empty)
// 没有type Level = Value下面会报错
println("======================")
println(checkLevel(Level.Overflow))
println(checkLevel(Overflow))
println(checkLevel(Level.High))
}
}
Operator
某些语言提供了操作复重载机制,即将一组挑选出来的字符保存下来,并赋予特殊的解析方式和行为。Scala使得所有字符都是平等的, 且处理所有方法的方式也是相同的,若他们碰巧看起来像操作符,也只是你的看法而已。因此,Scala没有提供重载操作符重载机制,而是选择了更加优雅的方式。
class SimpleTime(var hours: Int){
// def subtract(val other:SimpleTime){} // 报错,Error:identifier expected but 'val' found.
def subtract(other: SimpleTime): SimpleTime ={
// var ans: SimpleTime = _ // 报错,局部变量必须初始化
var ans: SimpleTime = new SimpleTime(0)
ans.hours = hours - other.hours
ans
}
def -(other: SimpleTime): SimpleTime ={
var ans: SimpleTime = new SimpleTime(0)
ans.hours = hours - other.hours
ans
}
def -=(other: SimpleTime): SimpleTime ={
hours -= other.hours
this
}
}
object Operator {
def main(args: Array[String]): Unit ={
val t1 = new SimpleTime(hours = 5);
val t2 = new SimpleTime(12);
println("=========subtract=========")
println((t2.subtract(t1).hours))
println((t2 subtract t1).hours)
println("===========-==============")
println((t2 - t1).hours) // 中缀法
println(t2.-(t1).hours)
println("==========(-=)============")
println("t2.hours: " + t2.hours)
t2 -= t1
println("after -=, t2.hours: " + t2.hours)
}
}
可见性
所有定义(值和方法)实际上会在执行类体的其他部分之前进行初始化。
用参数列表(主构造器)进行初始化的时候,如果想要变量在类外可见,需要显示的指定val或者var。默认的是val,内部不能进行修改,外部不能访问
class ClassArg1(a: Int, var name: String){
// 所有定义(值和方法)实际上会在执行类体的其他部分之前进行初始化
println(f)
def f(): Int ={
// a = a * 10 // 报错,Reassignment to val
a * 10
}
}
class ClassArg2(var a: Int)
class ClassArg3(val a: Int)
class VisibleClassArgs {
def main(args: Array[String]){
val ca = new ClassArg1(20, "PK")
ca.f
println("===================")
// a在类的外部不可以访问,如果希望a在类的外部也可以看见,需要将其定义为参数列表中的val和var
// println(ca.a)// 报错:value a is not a member of org.example.ch3.ClassArg1
println(ca.name)
}
}
元祖
通过将元素放到圆括号内创建元祖,且用元祖作为f的返回值。
将整个元祖捕获到单个val或var中,则可以通过._n这样的索引来选择每个元素,从1开始
case class Employee(name: String, ID: Int)
class Tuples{
// 通过将元素放到圆括号内创建元祖,且用元祖作为f的返回值
def f = (1, 3.14, "Mouse", false)
def main(args: Array[String]): Unit ={
/**
* 单个val后面跟着一个由5个标识符构成的元祖,表示对f返回的元祖进行拆包
*/
val (a, b, c, d) = f
println(s"$a $b $c $d")
/**
* 将整个元祖捕获到单个val或var中,则可以通过._n这样的索引来选择每个元素,从1开始
*/
val all = f
println(all)
println(all._1)
println(all._4)
println("===========case class===========")
/**
* 类似的形式拆包case类
*/
val empA = Employee("Bob", 1130)
val Employee(name, id) = empA
println(name)
}
}
ToString
在创建case类时会自动创建toString的方法
只要对某个对象操作时,期望得到一个String,则Scala会通过调用toString方法默默的为该对象产生一个String表示。
case class Bicycle(riders: Int)
class Surrey(val a: String)
class Surrey2(val a: String){
/**
* 重写toString方法,用override关键词
* @return
*/
override def toString = s"Surrey2 with $a"
}
object ToStringClass {
def main(args: Array[String]): Unit ={
val two = Bicycle(2)
println(two)
val fancy = new Surrey("top")
// 只要对某个对象操作时,期望得到一个String,
// 则Scala会通过调用toString方法默默的为该对象产生一个String表示。
// 不过这里的缺省的toString好像不能满足我们的需要,后面重写一下
println(fancy) // org.example.ch3.Surrey@6bdf28bb
val fancy2 = new Surrey2("top")
println(fancy2)
}
}
模式匹配
Java:对一个值进行条件判断,返回针对不同的条件进行不同的处理
变量 match { case value1 => 代码1 case value2 => 代码2 ...... case _ => 代码N } scala 不需要加break
🌰
// 加条件匹配
def judegGrade(name: String, grade: String): Unit={
grade match{
case "A" => println("Excellent ...") // scala 不需要加break
case "B" => println("Good ...")
case "C" => println("Just so so ...")
case _ if(name == "lisi") => println(name + "You are a good boy, but....")
case _ => println("You need work harder ...")
}
}
// Array匹配
def greeting(array: Array[String]): Unit ={
array match{
case Array("zhangsan") => println("Hi:zhangsan")
case Array(x, y) => println("Hi:" + x + " , " + y)
case Array("zhangsan", _*) => println("Hi:zhangsan and other friends...")
case _ => println("Hi: everybody")
}
}
// List匹配
def greeting(list: List[String]): Unit ={
//case "zhangsan" :: tail => println("list, Hi:zhangsan and other friends...")
//放的位置不一样输出结果也不一样,因为按顺序匹配,第一次能匹配上,就不会再匹配了
list match{ // 按顺序匹配,第一次能匹配上,就不会再匹配了,这个与函数的入参不一样
case "zhangsan":: Nil => println("list, Hi:zhangsan")
case "zhangsan" :: tail => println("list, Hi:zhangsan and other friends...")
case x::y::Nil => println("list, Hi:" + x + " , " + y)
// case "zhangsan" :: tail => println("list, Hi:zhangsan and other friends...")
case _ => println("list, Hi: everybody")
}
}
// 类型匹配,Any可以匹配任何类型
def matchType(obj: Any): Unit = {
obj match{
case x: Int => println("Int")
case s: String => println("String")
case m: Map[_, _] => m.foreach(println)
case _ => println("otherType")
}
}
class Person
case class CTO(name: String, floor: String) extends Person
case class Employee(name: String, floor: String) extends Person
case class Other(name: String) extends Person
// case class模式匹配
def caseClassMatch(person: Person): Unit ={
person match{
case CTO(name, floor) => println("CTO name is: " + name + ", floor is: " + floor)
case Employee(name, floor) => println("Employee name is: " + name + ", floor is: " + floor)
case _ => println("other")
}
}
// Some、None匹配
val grades = Map("PK" -> "A", "zhangsan" -> "C")
def getGrade(name: String): Unit ={
val grade = grades.get(name)
grade match{
case Some(grade) => println(name + ": your grade is " + grade)
case None => println("Sorry...")
}
}
getGrade("PK")
getGrade("zhangsan")
getGrade("Lily")