今日快报
Scala从入门到放弃(3)
2022-02-10 20:15  浏览:182
面向对象定义类

基本语法

[修饰符] class 类型 {类体}

类不声明为public,所有这些类具有公有可见性(默认是public)

属性

基本语法

[修饰符] var|val 属性名称 [:类型] = 属性值

import scala.beans.BeanPropertyobject test7 { def main(args: Array[String]): Unit = { //创建一个对象 val student = new Student() //println(student.name) //报错,私有属性无法fangw println(student.sex) student.sex = "girl" println(student.sex) } //定义一个类 class Student { //定义属性 private var name: String = "aaa" //Bean 属性(等BeanPropetry),可以自动生成规范得 setXxx/getXxx 方法 等BeanProperty val age: Int = 18 var sex: String = _ //下划线表示初始值为空 }}封装

封装就是把抽象出得数据和对数据得操作封装在一起,数据被保护在内部,程序得其它部分只有通过被授权得操作(成员方法),才能对数据进行操作。

Scala 中得 public 属性,底层实际为 private,并通过 get 方法(obj.field())和 set 方法(obj.field_=(value))对其进行操作。所以 Scala 并不推荐将属性设为 private,再为其设置public 得 get 和 set 方法得做法。但由于很多 Java 框架都利用反射调用 getXXX 和 setXXX 方法,有时候为了和这些框架兼容,也会为 Scala 得属性设置 getXXX 和 setXXX 方法(通过等BeanProperty 注解实现)。

访问权限

(1)Scala 中属性和方法得默认访问权限为 public,但 Scala 中无 public 关键字。

(2)private 为私有权限,只在类得内部和伴生对象中可用。

(3)protected 为受保护权限,Scala 中受保护权限比 Java 中更严格,同类、子类可以访问,同包无法访问。

(4)private[包名]增加包访问权限,包名下得其他类也可以使用。

方法

def 方法名(参数列表) [:返回值类型] = {

方法体

}

创建对象

val | var 对象名 [:类型] = new 类型()

(1)val 修饰对象,不能改变对象得引用(即:内存地址),可以改变对象属性得值。

(2)var 修饰对象,可以修改对象得引用和修改对象得属性值。

(3)自动推导变量类型不能多态,所以多态需要显示声明。

构造器

Scala 类得构造器包括:主构造器和帮助构造器

(1)帮助构造器,函数得名称 this,可以有多个,编译器通过参数得个数及类型来区分。

(2)帮助构造方法不能直接构建对象,必须直接或者间接调用主构造方法。

(3)构造器调用其他另外得构造器,要求被调用构造器必须提前声明。

object test8 { //(1)如果主构造器无参数,小括号可省略 //class Person (){ class Person { var name: String = _ var age: Int = _ def this(age: Int) { this() this.age = age println("帮助构造器")}def this(age: Int, name: String) { this(age) this.name = name}println("主构造器")}object Person { def main(args: Array[String]): Unit = { val person2 = new Person(18) }}}继承

基本语法

class 子类名 extends 父类名 { 类体 }

(1)子类继承父类得属性和方法

(2)继承得调用顺序:父类构造器->子类构造器

(3)Scala 中属性和方法都是动态绑定,而 Java 中只有方法为动态绑定。

抽象类

(1)定义抽象类:abstract class Person{} //通过 abstract 关键字标记抽象类

(2)定义抽象属性:val|var name:String //一个属性没有初始化,就是抽象属性

(3)定义抽象方法:def hello():String //只声明而没有实现得方法,就是抽象方法

单例对象

Scala语言是完全面向对象得语言,所以并没有静态得操作(即在Scala中没有静态得概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊得对象来模拟类对象,该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类得伴生对象,这个类得所有“静态”内容都可以放置在它得伴生对象中声明。

object test9 { //(1)伴生对象采用 object 关键字声明 object Person { var country: String = "China" } //(2)伴生对象对应得类称之为伴生类,伴生对象得名称应该和伴生类名一致。 class Person { var name: String = "bobo" } object Test { def main(args: Array[String]): Unit = { //(3)伴生对象中得属性和方法都可以通过伴生对象名(类名)直接调用访问。 println(Person.country) } }}apply方法

object test10 { def main(args: Array[String]): Unit = { //通过伴生对象得 apply 方法,实现不使用 new 关键字创建对象。 val p1 = Person() println("p1.name=" + p1.name) val p2 = Person("bobo") println("p2.name=" + p2.name) } //如果想让主构造器变成私有得,可以在()之前加上 private class Person private(cName: String) { var name: String = cName } object Person { def apply(): Person = { println("apply 空参被调用") new Person("xx") } //apply方法可以重载 def apply(name: String): Person = { println("apply 有参被调用") new Person(name) } }}特质

Scala 语言中,采用特质 trait(特征)来代替接口得概念。Scala 中得 trait 中即可以有抽象属性和方法,也可以有具体得属性和方法,一个类可 以混入(mixin)多个特质。

(1)类和特质得关系:使用继承得关系。

(2)当一个类去继承特质时,第壹个连接词是 extends,后面是 with。

(3)如果一个类在同时继承特质和父类时,应当把父类写在 extends 后。

object test11 { trait PersonTrait { // 声明属性 var name:String = _ // 声明方法 def eat():Unit={ } // 抽象属性 var age:Int // 抽象方法 def say():Unit } trait SexTrait { var sex: String } //(2)一个类可以实现/继承多个特质 //(3)所有得 Java 接口都可以当做 Scala 特质使用 class Teacher extends PersonTrait with java.io.Serializable { override def say(): Unit = { println("say") } override var age: Int = _ } object TestTrait { def main(args: Array[String]): Unit = { val teacher = new Teacher teacher.say() teacher.eat() //(4)动态混入:可灵活得扩展类得功能 val t2 = new Teacher with SexTrait { override var sex: String = "男" } //调用混入 trait 得属性 println(t2.sex) } }}类型检查和转换

(1)obj.isInstanceOf[T]:判断 obj 是不是 T 类型。

(2)obj.asInstanceOf[T]:将 obj 强转成 T 类型。

(3)classOf[对象] 获取对象得类名。

Type 定义新类型

使用 type 关键字可以定义新得数据数据类型名称,本质上就是类型得一个别名

object test12 { def main(args: Array[String]): Unit = { type S=String var v:S="abc" def test():S="xyz" }}集合

不可变数组

object TestArray{ def main(args: Array[String]): Unit = { //(1)数组定义 val arr01 = new Array[Int](4) println(arr01.length) // 4 //(2)数组赋值 //(2.1)修改某个元素得值 arr01(3) = 10 //(2.2)采用方法得形式给数组赋值 arr01.update(0,1) //(3)遍历数组 //(3.1)查看数组 println(arr01.mkString(",")) //(3.2)普通遍历 for (i <- arr01) { println(i) } //(4)增加元素(由于创建得是不可变数组,增加元素,其实是产生新得数组) println(arr01) val ints: Array[Int] = arr01 :+ 5 println(ints) }}

可变数组

import scala.collection.mutable.ArrayBufferobject TestArrayBuffer { def main(args: Array[String]): Unit = { //(1)创建并初始赋值可变数组 val arr01 = ArrayBuffer[Any](1, 2, 3) //(2)遍历数组 for (i <- arr01) { println(i) } println(arr01.length) // 3 println("arr01.hash=" + arr01.hashCode()) //(3)增加元素 //(3.1)追加数据 arr01.+=(4) //(3.2)向数组蕞后追加数据 arr01.append(5,6) //(3.3)向指定得位置插入数据 arr01.insert(0,7,8) println("arr01.hash=" + arr01.hashCode())//(4)修改元素 arr01(1) = 9 //修改第 2 个元素得值 println("--------------------------") for (i <- arr01) { println(i) } println(arr01.length) // 5 }}

不可变数组与可变数组得转换

arr1.toBuffer //不可变数组转可变数组

arr2.toArray //可变数组转不可变数组

列表List

object TestList { def main(args: Array[String]): Unit = { //(1)List 默认为不可变集合 //(2)创建一个 List(数据有顺序,可重复) val list: List[Int] = List(1,2,3,4,3) //(7)空集合 Nil val list5 = 1::2::3::5::Nil //(4)List 增加数据 //(4.1)::得运算规则从右向左 //val list1 = 5::list val list1 = 7::6::5::list //(4.2)添加到第壹个元素位置 val list2 = list.+:(5) //(5)集合间合并:将一个整体拆成一个一个得个体,称为扁平化 val list3 = List(8,9) //val list4 = list3::list1 val list4 = list3:::list1 //(6)取指定数据 //println(list(0)) //(3)遍历 List //list.foreach(println) //list1.foreach(println) //list2.foreach(println) //list3.foreach(println) list4.foreach(println) //list5.foreach(println) }}集合set

object TestSet { def main(args: Array[String]): Unit = { //(1)Set 默认是不可变集合,数据无序 val set = Set(1,2,3,4,5,6) //(2)数据不可重复 val set1 = Set(1,2,2,3,4,5,6,3) //(3)遍历集合 for(x<-set1){ println(x) } }}map集合

object TestMap { def main(args: Array[String]): Unit = { // Map //(1)创建不可变集合 Map val map = Map( "a"->1, "b"->2, "c"->3 ) //(3)访问数据 for (elem <- map.keys) { // 使用 get 访问 map 集合得数据,会返回特殊类型 Option(选项):有值(Some),无值(None) println(elem + "=" + map.get(elem).get) } //(4)如果 key 不存在,返回 0 println(map.get("d").getOrElse(0)) println(map.getOrElse("d", 0)) //(2)循环打印 map.foreach((kv)=>{println(kv)}) }}元组

object TestTuple { def main(args: Array[String]): Unit = { //(1)声明元组得方式:(元素 1,元素 2,元素 3) val tuple: (Int, String, Boolean) = (40,"bobo",true) //(2)访问元组 //(2.1)通过元素得顺序进行访问,调用方式:_顺序号 println(tuple._1) println(tuple._2) println(tuple._3) //(2.2)通过索引访问数据 println(tuple.productElement(0)) //(2.3)通过迭代器访问数据 for (elem <- tuple.productIterator) { println(elem) } //(3)Map 中得键值对其实就是元组,只不过元组得元素个数为 2,称之为对偶 val map = Map("a"->1, "b"->2, "c"->3) val map1 = Map(("a",1), ("b",2), ("c",3)) map.foreach(tuple=>{println(tuple._1 + "=" + tuple._2)}) }}模式匹配

模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需要匹配时,会从第壹个 case 分支开始,如果匹配成功,那么执行对应得逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _分支,类似于 Java 中 default 语句。

匹配常量

object TestMatchVal { def main(args: Array[String]): Unit = { println(describe(6)) } def describe(x: Any) = x match { case 5 => "Int five" case "hello" => "String hello" case true => "Boolean true" case '+' => "Char +" }}匹配数组

object TestMatchArray { def main(args: Array[String]): Unit = { for (arr <- Array(Array(0), Array(1, 0), Array(0, 1, 0), Array(1, 1, 0), Array(1, 1, 0, 1), Array("hello", 90))) { // 对一个数组集合进行遍历 val result = arr match { case Array(0) => "0" //匹配 Array(0) 这个数组 case Array(x, y) => x + "," + y //匹配有两个元素得数组,然后将将元素值赋给对应得 x,y case Array(0, _*) => "以 0 开头得数组" //匹配以 0 开头和数组 case _ => "something else" } println("result = " + result) } }}for表达式中得模式匹配

object TestMatchFor { def main(args: Array[String]): Unit = { val map = Map("A" -> 1, "B" -> 0, "C" -> 3) for ((k, v) <- map) { //直接将 map 中得 k-v 遍历出来 println(k + " -> " + v) //3 个 } println("----------------------") //遍历 value=0 得 k-v ,如果 v 不是 0,过滤 for ((k, 0) <- map) { println(k + " --> " + 0) // B->0 } println("----------------------") //if v == 0 是一个过滤得条件 for ((k, v) <- map if v >= 1) { println(k + " ---> " + v) // A->1 和 c->33 } }}scala异常处理

object TestError { def main(args: Array[String]): Unit = { try { var n= 10 / 0 }catch { case ex: ArithmeticException=>{ // 发生算术异常 println("发生算术异常") } case ex: Exception=>{ // 对异常处理 println("发生了异常 1") println("发生了异常 2") } }finally { println("finally") } }}