日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

重游scala04

發布時間:2024/2/28 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 重游scala04 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Scala編程

?

?

課程大綱

課程內容

學習效果

掌握目標

Scala編程數據結構

Scala類、對象

掌握

熟練掌握類的定義,創建對象

熟練掌握繼承和特質

熟練掌握樣例類、模式匹配

?

Scala繼承

掌握

Scala特質

掌握

Scala樣例類

掌握

Scala模式匹配

掌握

?

?

Scala的類與Java、C++的類比起來更簡潔,學完之后你會更愛Scala!!!

一、類

1、類的定義

Scala 訪問修飾符有:private,protected,public。

//在Scala中,類的定義可以通過class關鍵字實現,類并不用聲明為public。

//Scala源文件中可以包含多個類,所有這些類都具有公有可見性。

class Dog {

??//屬性必須有初始值,如果不想有初始值初始化為_下劃線,賦值為_是必須指定數據類型

??private var?leg = 4

??def shout(content: String) {

????println(content)

??}

??def currentLeg = leg

}

?

使用這個類:

//在Scala中,類并不用聲明為public。默認就是public

val dog = new Dog

//調用方法,通過對象.方法 對象+空格+方法

dog shout "汪汪汪"

dog.shout("汪汪汪")

println(dog currentLeg)

println(dog.currentLeg)

//訪問屬性,通過對象.屬性 對象+空格+屬性

dog.leg = 4

println(“leg = “+dog.leg)

dog leg = 4

println(dog leg)

?

//在Scala中,類并不用聲明為public。

//Scala源文件中可以包含多個類,所有這些類都具有公有可見性。

class Person {

??//用val修飾的變量是只讀屬性,有getter但沒有setter

??//(字面量,相當與Java中用final修飾的變量)

??val id?= "9527"

??//用var修飾的變量既有getter又有setter

??var age: Int = 18

// _代表初始值,使用時屬性必須指定類型

var color:Strng =?_

??//類私有字段,只能在伴生對象和類的內部使用

??private var name: String = "唐伯虎"

??//對象私有字段,訪問權限更加嚴格的,當前對象的字段只能被Person類的方法訪問到

//對象私有字段,只能在類的內部使用
??private[this] val pet = "小強"

}

?

尖叫提示:在Scala中,類并不聲明為Public,一個Scala源文件可以包含多個類。所有這些類都具有公有可見性。調用無參方法時,可以加(),也可以不加;如果方法定義不帶括號,那么調用時就不能帶括號

2、Getter?Setter方法

對于scala類中的每一個屬性,編譯后,會有一個私有的字段和相應的getter、setter方法生成:

//getter

println(dog leg)

//setter

//對象.屬性_=(值)

dog.leg_=(10)

println(dog currentLeg)

當然了,你也可以不使用自動生成的方式,自己定義getter和setter方法

class Dog2 {

??private var _leg = 4

??def leg = _leg

??def leg_=(newLeg: Int) {

????_leg = newLeg

??}

}

使用之:

val dog2 = new Dog2

dog2.leg_=(10)

println(dog2.leg)

?

尖叫提示:自己手動創建變量的getter和setter方法需要遵循以下原則:

1) 字段屬性名以“_”作為前綴,如:_leg

2)?getter方法定義為:def leg = _leg

3) setter方法定義時,方法名為屬性名去掉前綴,并加上后綴,后綴是:“leg_=”,如例子所示

?

3、Bean屬性

JavaBeans規范定義了Java的屬性是像getXXX()和setXXX()的方法。許多Java工具都依賴這個命名習慣。為了Java的互操作性。將Scala字段加@BeanProperty時,這樣的方法會自動生成。

創建一個Bean,使用@BeanProperty注解標識某個屬性變量

import scala.beans.BeanProperty

class Person {

??@BeanProperty var name: String = _

}

使用@BeanProperty注解標識的屬性只能以字母開頭,不能下劃線開頭。

?

通過getName、setName訪問屬性

val person = new Person

person.setName("Nick")

person.getName

println(person.name)

尖叫提示:

Person將會生成四個方法:

--name:String

--name_=(newValue:String): Unit

--getName():String

--setName(newValue:String):Unit

?

?

4、構造器

scala中構造分為主構造器和輔助構造器

注意:主構造器會執行類定義中的所有語句

/**

??*每個類都有主構造器,主構造器的參數直接放置類名后面,與類交織在一起

??*/

class Student(val name: String, val age: Int){

??//主構造器會執行類定義中的所有語句

??println("執行主構造器")

?

??private var gender = "male"

??//用this關鍵字定義輔助構造器
??def this(name: String, age: Int, gender: String){
????//每個輔助構造器必須以主構造器或其他的輔助構造器的調用開始

this(name, age)
????println("執行輔助構造器")
????this.gender = gender
??}

}

?

//主構造器中name屬性沒有初始值,age屬性有初始值,那么在調用主構造創建對象是,可以不傳age這個參數的值

class?Teacher(var name:String,var age:Int=30) {

}

//如果在主構造器中屬性有初始值,那么在調用主構造創建對象是,可以不傳這個參數的值

val?t01 = new Teacher("xiaoming")
println(" t01 name "+t01.name)
println("t01 age = "+t01.age)

?

?

尖叫提示:

(1)如果在主構造器中定義的參數不帶val或var,這定義的參數不是類的屬性,不能通過“對象.參數名稱”?調用;

(2)如果在主構造器中定義的參帶val或var,這定義的參數提升為類的屬性,能通過“對象.參數名稱”?調用;

(3)如果構造器參數不帶val或var,但是參數被一個方法所使用,那么它將會被提升為類的屬性。

?

?

Scala 中的 private 限定符,比 Java 更嚴格,在嵌套類情況下,外層類甚至不能訪問被嵌套類的私有成員。

用 private 關鍵字修飾,帶有此標記的成員僅在包含了成員定義的類或對象內部可見,同樣的規則還適用內部類。

?

?

?

  • 對象

1、對象

Object定義的結構中的屬性和方法,是靜態的。存放工具方法和常量,即靜態的方法和屬性。

?

object Constants{
??val path = "aaaaa"
}
object StringUtil{
??def concat(a:String, b:String)= a+b
}

2、伴生對象

在Scala的類中,與類名相同的對象叫做伴生對象。利用伴生對象,可以實現單例。

//類A后面加了private,那么主構造器就變為私有了,外部不能new實例
class A private{
??println("我是類")
}
object A{
??//但是伴生對象可以調用私有的主構造器
??println("我是伴生對象"+new A())
}

?

//以下代碼實現單例
class SingleTon private{
??println("我是類")
}
object SingleTon{
??private val _instance = new SingleTon
??def instance = _instance
}

?

伴生類和伴生對象之間可以相互訪問私有的方法和屬性。也就是說,伴生類和伴生對象之間不受private限制。

package cn.bigdata.scala

class Dog {
??val id = 1
??private var name = "bigdata"

??def printName(): Unit ={
????//在Dog類中可以訪問伴生對象Dog的私有屬性
????println(Dog.CONSTANT + name )
??}
}

/**
??* 伴生對象
??*/
object Dog {

??//伴生對象中的私有屬性
??private val CONSTANT = "汪汪汪 : "

??def main(args: Array[String]) {
????val p = new Dog
????//訪問私有的字段name
????p.name = "123"
????p.printName()
??}
}

?

3、apply方法

通常我們會在類的伴生對象中定義apply方法。

object Teacher {
??println("我是對象Teacher")
??//調用Teacher()時,apply()方法會被調用
??def apply() = {println("我是apply()")}
}

?

?

?

?

一般,在伴生對象中會寫apply()方法,用于創建伴生類的實例。

當遇到類名(參數1,...參數n)時apply方法會被調用

package cn.bigdata.scala


object ApplyDemo {

??def main(args: Array[String]) {

//調用了Array伴生對象的apply方法

//def apply(x: Int, xs: Int*): Array[Int]

//arr1中只有一個元素5
????val arr1 = Array(5)
????println(arr1.toBuffer)

????//new了一個長度為5的array,數組里面包含5個null
????var arr2 = new Array(5)
??}
}

?

class?Dog(name:String) {
??var age:Int = 0
??def this(name:String,age:Int){
????this(name)
????this.age = age
??}
}
object Dog{
??def apply(name: String): Dog ={
????println("一個參數的apply");
????new Dog(name)
??}
??def apply(name: String,age:Int):Dog={
????println("兩個參數的apply");
????new Dog(name,age)
??}

??def main(args: Array[String]): Unit = {
????var a1 = Dog

//通過一個參數的apply創建對象,Dog會變成斜體
????var a2= ?Dog("lisi")

//通過兩個參數的apply創建對象
????var a3 = Dog("lisi",23)
??}
}

?

class Cat(var name:String, var age:Int) {
???var sex:Char = 'c'
???def this(name:String,age:Int,sex:Char){
????this(name,age)
????this.sex = sex
??}
}

object Cat{
??def apply(name:String,age:Int) = {
????println("這是伴生對象的兩個參數apply方法")
????new Cat(name,age)
??}
??def apply(name:String,age:Int,sex:Char)={
????println("這是伴生對象的三個參數apply方法")
????new Cat(name,age,sex)
??}
??def main(args: Array[String]): Unit = {
????var cat01 = new Cat("bosimao",1)
????var cat02 = Cat("bosimao",1)
????var cat03 = new Cat("bosimao",2,'1')
????var cat04 = Cat("bosimao",2,'1')
??}
}

?

4、應用程序對象

Scala程序都必須從一個對象的main方法開始,可以通過擴展App特質,不寫main方法。

?

package cn.bigdata.scala

object AppObjectDemo extends App{
??//不用寫main方法
??println("I love you Scala")
}

?

  • 繼承

1、繼承類

在Scala中擴展類的方式和Java一樣都是使用extends關鍵字

scala中不支持多繼承。

?

和Java一樣使用extends關鍵字,在定義中給出子類需要而超類沒有的字段和方法,或者重寫超類的方法。

?

class?Person ?{

??var?name = ""

}

?

class?Employee extends?Person{

??var?salary = 0.0

??def?description = "員工姓名:" + name + " 薪水:" + salary

}

尖叫提示:如果類聲明為final,他將不能被繼承。如果單個方法聲明為final,將不能被重寫。

2、類型檢查和轉換

Scala

Java

含義

obj.isInstanceOf[C]

obj instanceof C

判斷obj是不是C類型,返回boolean的值

obj.asInstanceOf[C]

(C)obj

將obj強制轉換成C類型,返回類實例

classOf[C]

C.class

返回class

?

?val a1 = new A1
?//返回true
?println(a1.isInstanceOf[A1])
?//返回false
println(a1.isInstanceOf[List[Int]])
?//返回class day031$A1
?println(a1.asInstanceOf[A].getClass)
?//報錯java.lang.ClassCastException: day031$A1 cannot be cast to scala.collection.immutable.List
?println(a1.asInstanceOf[List[Int]].size)

?

//返回class day031$A1
println(classOf[A1])
//返回class day031$A1
println(a1.getClass)

?

3、重寫方法

在Scala中重寫一個非抽象的方法必須使用override修飾符,調用超類的方法使用super關鍵字

class?Person {
??var name = ""
??override def toString = getClass.getName + "[name=" + name + "]"
}

class Employee extends Person {
??var salary = 0.0
??override def toString = super.toString + "[salary=" + salary + "]"
}

?

?

4、超類的構造

輔助構造器會調用主構造器,主構造器可以調用超類的構造器。

class?Person(val name: String, val age: Int) {
??override def toString = getClass.getName + "[name=" + name +
????",age=" + age + "]"
}
class Employee(name: String, age: Int, val salary : Double) extends Person(name, age) {
??override def toString = super.toString + "[salary=" + salary + "]"
}

輔助構造器永遠都不可能直接調用超類的構造器,所以你不能調用super(params)因為supre用在輔助構造器中。

5、重名字段

子類改寫父類或者抽象父類的字段,通過以下方式:

??class A{
????val name:String = "張三"
????def sleep() = "8 hours" ??//這是無參的方法
??}
??class A1 extends A{
????override val name="歷史"

????override val sleep: String = {"9 hours"} ?//這里理解為屬性
??}

??val a = new A()
??println(a.name)
??println(a.sleep)
??val a1 = new A1()
??println(a1.name)
??println(a1.sleep)
// ?println(a1.sleep()) //編譯錯誤

尖叫提示:

1、val屬性只能重寫另一個val屬性參的def同名方法

2、var不能重寫var屬性,但能重寫抽象的var屬性

6、抽象類

可以通過abstract關鍵字標記不能被實例化的類。

在抽象類中,沒有方法體的方法是抽象方法。沒有初始值的屬性是抽象屬性。

abstract class A{
??var name:String //抽象屬性
??def desc:String //抽象方法
}

class A1 extends A{
??//實現屬性,可以不加override,也可以加
??override var name: String = "zhangsan"
??//實現方法,可以不加override,也可以加
??override def desc: String = "aaaaaaaa"
}

val a1 = new A1()
println(a1.name)
println(a1.desc)

?

?

  • 特質
  • 1)不允許多重繼承

    所有的面向對象的語言都不允許直接的多重繼承,因為會出現“deadly diamond of death”問題。Scala提供了trait(特質),特質可以同時擁有抽象方法和具體方法,一個類可以實現多個特質。

    2)當做接口使用的特質

    特質中沒有實現的方法就是抽象方法。類通過extends繼承特質,通過with可以繼承多個特質。

    trait?Logger {
    ??def log(msg: String)
    }

    class ConsoleLogger extends Logger with Cloneable with Serializable {
    ??def log(msg: String) {
    ????println(msg)
    ??}
    }

    Logger with Cloneable with Serializable是一個整體,extends這個整體

    所有的java接口都可以當做Scala特質使用。

    3帶有具體實現的特質

    特質中的方法并不一定是抽象的:

    trait?ConsoleLogger {
    ??def log(msg: String) {
    ????println(msg)
    ??}
    }

    class Account {
    ??protected var balance = 0.0
    }

    class SavingsAccount extends Account with ConsoleLogger {
    ??def withdraw(amount: Double) {
    ????if (amount > balance) log("余額不足")
    ????else balance -= amount
    ??}
    }

    ?

    ?

    ?

    //這是一個接口

    trait?Animal {

    //定義一個抽象方法
    ??def sleep

    //定義一個實現的方法,普通方法
    ??def eat(): Unit ={
    ????println("這是接口中的一個方法,已經實現")
    ??}
    }

    ?

    //定義一個類去繼承接口,使用關鍵字extends

    class?Emp extends Animal{

    ??//實現它的抽象方法,關鍵字override 可有可無
    ??override def sleep: Unit = {
    ????println("繼承接口,并實現抽象方法")
    ??}

    ??//重寫已經實現的方法,關鍵字override 必須有

    ??override def eat(): Unit = {
    ????println("繼承接口,并重寫已經實現的方法")
    ??}
    }

    ?

    // extends 繼承一個類/抽象類 ?with 實現接口
    // 實現多個接口:with 接口1 with 接口2
    class Student extends Human with Animal with Flyable{
    ??override def work: Unit = {
    ????println("繼承抽象類,并實現抽象方法")
    ??}
    ??override def sleep: Unit = {
    ????println("實現接口,并實現抽象方法")
    ??}
    }

    ?

  • 為實例混入特質
  • 在創建類的實例時,可以指定某個實例混入特質。那么,只有這個實例有特質,其他實例沒有。

    trait Logger{
    ??def log(msg:String)=println("日志 "+msg)
    }
    class A{}
    class A1 extends A ?{
    }

    val a1 = new A1()
    println(a1)
    //實例a2混入特質,有log方法;a1沒有
    val a2 = new A1() with Logger
    a2.log("aaaaaaaaa")

    ?

  • 特質調用鏈
  • 如果類繼承多個特質,那么特質中的方法會依次執行,類似于責任者模式。

    需要讓特質中的方法最后調用super。

    trait Logger{
    ??def log(msg:String)=println("Logger日志 "+msg)
    }
    trait FileLogger extends Logger {
    ??override def log(msg: String): Unit = {
    ????println("FileLogger日志 "+msg)
    ????//必須調用super
    ????super.log(msg)
    ??}
    }
    trait HDFSLogger extends FileLogger {
    ??override def log(msg: String): Unit = {
    ????println("HDFSLogger日志 "+msg)
    ????//必須調用super
    ????super.log(msg)
    ??}
    }

    class A{}
    val a2 = new A() with Logger with FileLogger with HDFSLogger
    //從右向左,依次調用各個特質中的log方法
    a2.log("aaaaaaaaa")

    ?

    ?

    ?

    四、模式匹配和樣例類

    Scala有一個十分強大的模式匹配機制,可以應用到很多場合:如switch?case語句、類型檢查等。Java中的switch是按照類型判斷的,這里的模式匹配則可以不限制類型,功能更加強大。

    1、匹配

    與default等效的是捕獲所有的case_ 模式。如果沒有模式匹配,拋出MatchError,每個case中,不用break語句。可以在match中使用任何類型可以是字符串也可以是數字,而不僅僅是數字。

    package cn.bigdata.cases
    import scala.util.Random

    object CaseDemo01 extends App{
    ??val arr = Array("a", "b", "c")
    ??val name = arr(Random.nextInt(arr.length))

    ??//匹配到case 后面的值,就執行=> 后面的內容
    ??//沒有匹配到就 匹配_, 執行 => 后面的內容

    ??name match {
    ????case "a" => println("aa...")
    ????case "b" => println("bb...")
    ????case _ => println("真不知道你們在說什么...")
    ??}
    }

    尖叫提示:如果把case _作為第一個case,則永遠匹配 case _

    ??????????如果沒有case_ ,且match中沒有匹配的case,則會拋出異常,scala.MatchError

    //模式匹配結果作為函數返回值
    def patternShow(x : Any) = x match {
    ??case 5 => "五"
    ??case true => "真"
    ??case "test" => "字符串"
    ??case null => "null值"
    ??case Nil => "空列表"
    ??case _ => "其他常量"
    }
    println(patternShow(5))
    println(patternShow(true))
    println(patternShow(List()))

    ?

  • 匹配變量
  • 變量匹配,匹的是case語句后面接的是scala變量,如case x if(x == 5) => x等,在使用時一般會加守衛條件,當然也可以像case x => x這樣使用,它會匹配任何輸入的合法變量。

    //模式匹配結果作為函數返回值
    def patternShow(x : Any) = x match {
    ??case x if (x == 5) => x
    ??case x if (x == "Scala") => x
    ??case _ =>
    }
    println(patternShow(5))
    println(patternShow("Scala"))

    ?

    ?

  • 匹配類型
  • 它可以匹配輸入待匹配變量的類型。

    object TypePattern{

      def main(args:Array[String]) :Unit = {

      def typePattern(t : Any) = t match {{

        case t : String => "String"

        case t : Int => "Intger"

        case t : Double => "Double"

        case _ => "Other Type"

      }

      println(typePattern(5.0))

      println(typePattern(5))

      println(typePattern("5"))

      println(typePattern(List()))

      }

    }

    4、匹配數組、列表、元組

    package cn.bigdata.cases

    object CaseDemo03 extends App{

    ??val arr = Array(1, 3, 5)
    ??arr match {
    ????case Array(1, x, y) => println(x + " " + y)
    ????case Array(0) => println("only 0")
    ????case Array(0, _*) => println("0 ...")
    ????case _ => println("something else")
    ??}

    //_ 表示一個元素的通配符

    //_*?表示0個或者多個元素的通配符

    ??val lst = List(3, -1)
    ??lst match {
    ????case 0 :: Nil => println("only 0")

    case?_ ::Nil => println("List 只有一個元素的List,這個元素是任意值")
    ????case x :: y :: Nil => println(s"x: $x?y: $y")
    ????case 0 :: tail => println("0 ...")
    ????case _ => println("something else")
    ??}

    ??val tup = (2, 3, 7)
    ??tup match {
    ????case (1, x, y) => println(s"1, $x?, $y")
    ????case (_, z, 5) => println(z)
    ????case ?_ => println("else")
    ??}

    //元組只能匹配內容,固定長度的元組只能匹配對應長度的元組,只是配置內容,不能匹配長度
    }

    ?

    注意:在Scala中列表要么為空(Nil表示空列表)要么是一個head元素加上一個tail列表。

    9 :: List(5, 2) ?:: 操作符是將給定的頭和尾創建一個新的列表

    注意:: 操作符是右結合的,如9 :: 5 :: 2 :: Nil相當于 9 :: (5 :: (2 :: Nil))

    五、異常

    當碰到異常情況時,方法拋出一個異常,終止方法本身的執行,異常傳遞到其調用者,調用者可以處理該異常,也可以升級到它的調用者。運行系統會一直這樣升級異常,直到有調用者能處理它。 如果一直沒有處理,則終止整個程序。

    Scala的異常的工作機制和Java一樣,但是Scala沒有“checked”異常,你不需要聲明說函數或者方法可能會拋出某種異常。受檢異常在編譯器被檢查,java必須聲明方法所會拋出的異常類型。

    拋出異常:用throw關鍵字,拋出一個異常對象。所有異常都是Throwable的子類型。throw表達式是有類型的,就是Nothing,因為Nothing是所有類型的子類型,所以throw表達式可以用在需要類型的地方。

    捕捉異常:在Scala里,借用了模式匹配的思想來做異常的匹配,因此,在catch的代碼里,是一系列case字句。

    異常捕捉的機制與其他語言中一樣,如果有異常發生,catch字句是按次序捕捉的。因此,在catch字句中,越具體的異常越要靠前,越普遍的異常越靠后。 如果拋出的異常不在catch字句中,該異常則無法處理,會被升級到調用者處。

    finally字句用于執行不管是正常處理還是有異常發生時都需要執行的步驟,一般用于對象的清理工作。

    object?ExceptionSyllabus {

    ??def divider(x: Int, y: Int): Float= {
    ????if(y == 0) throw new Exception("0作為了除數")
    ????else x / y
    ??}

    ??def main(args: Array[String]): Unit = {
    ????try {
    ??????println(divider(10, 3))
    ????} catch {
    ??????case ex: Exception => println("捕獲了異常:" + ex)
    ????} finally {}
    ??}
    }

    ?

    ?

    、樣例類

    在Scala中樣例類是一中特殊的類case class,默認實現了Serializable。case class是多例的,后面要跟構造參數,case object是單例的。

    ?

    當你聲明了一個 case class,Scala 編譯器為你做了這些:

  • 創建 case class 和它的伴生 object
  • 實現了 apply 方法讓你不需要通過 new 來創建類實例
  • 默認為主構造函數參數列表的所有參數前加 val
  • 添加天然的 hashCode、equals 和 toString 方法。由于 == 在 Scala 中總是代表 equals,所以 case class 實例總是可比較的
  • 生成一個 copy 方法以支持從實例 a 生成另一個實例 b,實例 b 可以指定構造函數參數與 a 一致或不一致
  • ?

    case class A(id:Int, name:String, age:Int);
    //使用伴生對象創建實例
    val a = A(1,"張三", 23)
    //輸出A(1,張三,23)
    println(a)
    //已經覆蓋copy方法
    val b = a.copy()
    //輸出A(1,張三,23)
    println(b)
    //輸出true
    println(a==b)

    ?

    Case class可以用于模式匹配。

    //定義樣例類
    case class Address(street: String, city: String, country: String)
    case class Person(name: String, age: Int, address: Address)
    //創建實例
    val alice = Person("Alice", 12, Address("1 hello world", "2 hello world", "CN"))
    val bob = Person("Bob", 12, Address("1 hello world", "2 hello world", "CN"))
    val charlie = Person("Charlie", 12, Address("1 hello world", "2 hello world", "CN"))

    for (person <- Seq(alice, bob, charlie)) {
    ??person match { ?//匹配實例值,使用==判斷
    ????case Person("Alice", 12, Address(_, "2 hello world", _)) => println("hi alice")
    ????case Person("Bob", 12, Address("1 hello world", "2 hello world", "CN")) => println("hi bob")
    ????case Person(name, age, _) => println("who are you?")
    ??}
    }

    ?

    超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

    總結

    以上是生活随笔為你收集整理的重游scala04的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。