1、 Scala的面向?qū)ο笏枷牒蚃ava的面向?qū)ο笏枷牒透拍钍且恢碌摹?br> 2、Scala中語法和Java不同,補充了更多的功能。
6.1 Scala包
1)基本語法
package 包名
- 1
2)Scala包的三大作用(和Java一樣)
1、區(qū)分相同名字的類
2、當類很多時,可以很好的管理類
3、控制訪問范圍
6.1.1 包的命名
1)命名規(guī)則
只能包含數(shù)字、字母、下劃線、小圓點,但不能用數(shù)字開頭,也不要使用關鍵字。
2)案例實操文章來源地址http://www.zghlxwxcb.cn/news/detail-647346.html
demo.class.execl //錯誤,因為class關鍵字
demo.12a //錯誤,數(shù)字開頭
- 1
- 2
3)命名規(guī)范
一般是小寫字母 + 小圓點
com.公司名.項目名.業(yè)務模塊名
4)案例實操
com.itcast.oa.model
com.itcast.oa.controller
com.sohu.bank.order
- 1
- 2
- 3
6.1.2 包說明(包語句)
1)說明
Scala有兩種包的管理風格,一種方式和Java的包管理風格相同,每個源文件一個包(包名和源文件所在路徑不要求必須一致),包名用 “.” 進行分隔以表示包的層級關系,如com.atguigu.scala。另一種風格,通過嵌套的風格表示層級關系,如下
package com{
package atguigu{
package scala{
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
第二種風格有以下特點:
(1)一個源文件中可以聲明多個package
(2)子包中的類可以直接訪問父包中的內(nèi)容,而無需導包文章來源:http://www.zghlxwxcb.cn/news/detail-647346.html
2)案例實操
package com {
import com.atguigu.Inner //父包訪問子包需要導包
object Outer {
val out: String = "out"
def main(args: Array[String]): Unit = {
println(Inner.in)
}
}
package atguigu {
object Inner {
val in: String = "in"
def main(args: Array[String]): Unit = {
println(Outer.out) //子包訪問父包無需導包
}
}
}
}
package other {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
6.1.3 包對象
在Scala中可以為每個包定義一個同名的包對象,定義在包對象中的成員,作為其對應包下所有class和object的共享變量,可以被直接訪問。
1)定義
package object com{
val shareValue="share"
def shareMethod()={}
}
- 1
- 2
- 3
- 4
2)說明
1、若使用Java的包管理風格,則包對象一般定義在其對應包下的package.scala文件中,包對象名與包名保持一致。
2、如采用嵌套方式管理包,則包對象可與包定義在同一文件中,但是要保證包對象與包聲明在同一作用域中。
package com {
object Outer {
val out: String = "out"
def main(args: Array[String]): Unit = {
println(name)
}
}
}
package object com {
val name: String = "com"
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
6.1.4 導包說明
1)和 Java 一樣,可以在頂部使用 import 導入,在這個文件中的所有類都可以使用。
2)局部導入:什么時候使用,什么時候?qū)搿T谄渥饔梅秶鷥?nèi)都可以使用
3)通配符導入:import java.util._
4)給類起名:import java.util.{ArrayList=>JL}
5)導入相同包的多個類:import java.util.{HashSet, ArrayList}
6)屏蔽類:import java.util.{ArrayList =>,}
7)導入包的絕對路徑:new root.java.util.HashMap
package java {
package util {
class HashMap {
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
說明:
2)注意:
Scala中三個默認導入分別是:
import java.lang._
import scala._
import scala.Predef._
6.2 類和對象
類:可以看成一個模板
對象:表示具體的事物
6.2.1 定義類
1)回顧:Java中的類
如果類是public的,則必須和文件名一致。
一般,一個.java有一個public類
注意:Scala中沒有public,一個.scala中可以寫多個類。
2)基本語法
[修飾符] class 類名 {
類體
}
- 1
- 2
- 3
說明:
1、Scala語法中,類并不聲明為public,所有這些類都具有共有可見性(即默認就是public)
2、一個Scala源文件可以包含多個類
3)案例實操
package com.atguigu.chapter06
//(1)Scala 語法中,類并不聲明為 public,所有這些類都具有公有可見性(即默認就是 public)
class Person {
}
//(2)一個 Scala 源文件可以包含多個類
class Teacher{
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
6.2.2 屬性
屬性是類的一個組成部分
1)基本語法
[修飾符] var|val 屬性名稱 [:類型] = 屬性值
- 1
注:Bean 屬性(@BeanPropetry),可以自動生成規(guī)范的 setXxx/getXxx 方法
2)案例實操
package com.atguigu.scala.test
import scala.beans.BeanProperty
class Person {
var name: String = "bobo" //定義屬性
var age: Int = _ // _表示給屬性一個默認值
//Bean 屬性(@BeanProperty)
@BeanProperty var sex: String = "男"
//val 修飾的屬性不能賦默認值,必須顯示指定
}
object Person {
def main(args: Array[String]): Unit = {
var person = new Person()
println(person.name)
person.setSex("女")
println(person.getSex)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
6.3 封裝
封裝就是把抽象出的數(shù)據(jù)和對數(shù)據(jù)的操作封裝在一起,數(shù)據(jù)被保護在內(nèi)部,程序的其它部分只有通過被授權(quán)的操作(成員方法),才能對數(shù)據(jù)進行操作。Java封裝操作如下。
1、將屬性進行私有化
2、提供一個公共的set方法,用于對屬性賦值
3、提供一個公共的get方法,用于獲取屬性的值
Scala中的public屬性,底層實際為private,并通過get方法(obj.field())和set方法(obj.field_ = (value))對其進行操作。所以Scala并不推薦將屬性設為private,再為其設置public的get和set方法的做法。但由于很多java框架都利用反射調(diào)用getXXX和setXXX方法,有時候為了這些框架兼容,也會為Scala的屬性設置getXXX和setXXX方法(通過@BeanProperty注解實現(xiàn))。
6.3.1 訪問權(quán)限
1)說明
再java中,訪問權(quán)限分為:public,private,protected和默認。在Scala中,你可以通過類似的修飾符達到同樣的效果。但是使用上有區(qū)別。
1、Scala中屬性和方法的默認訪問權(quán)限為public,但Scala中無public關鍵字。
2、private為私有權(quán)限,只在類的內(nèi)部和伴生對象中可用。
3、protected為受保護權(quán)限,Scala中受保護權(quán)限比Java中更嚴格,同類、子類可以訪問,同包無法訪問。
4、private[包名]增加包訪問權(quán)限,包名下的其他類也可以使用
2)案例實操
package com.atguigu.scala.test class Person { private var name: String = "bobo" protected var age: Int = 18 private[test] var sex: String = "男" def say(): Unit = { println(name) } } object Person { def main(args: Array[String]): Unit = { val person = new Person person.say() println(person.name) println(person.age) } } class Teacher extends Person { def test(): Unit = { this.age this.sex } } class Animal { def test: Unit = { new Person().sex } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
6.3.2 方法
1)基本語法
def 方法名(參數(shù)列表)[: 返回值類型] = {
方法體
}
- 1
- 2
- 3
2)案例實操
class Person {
def sum(n1:Int, n2:Int) : Int = {
n1 + n2
}
}
object Person {
def main(args: Array[String]): Unit = {
val person = new Person()
println(person.sum(10, 20))
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
6.3.3 創(chuàng)建對象
1)基本語法
val | var 對象名[: 類型] = new 類型()
- 1
2)案例實操
1、val修飾對象, 不能改變對象的引用(即:內(nèi)存地址),可以改變對象屬性的值。
2、var修飾對象,可以修改對象的引用和修改對象的屬性值
3、自動推導變量類型不能多態(tài),所以多態(tài)需要聲明
class Person {
var name: String = "canglaoshi"
}
object Person {
def main(args: Array[String]): Unit = {
//val 修飾對象,不能改變對象的引用(即:內(nèi)存地址),可以改變對象屬
性的值。
val person = new Person()
person.name = "bobo"
// person = new Person()// 錯誤的
println(person.name)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
6.3.4 構(gòu)造器
1、和Java一樣,Scala構(gòu)造對象也需要調(diào)用構(gòu)造方法,并且可以有任意多個構(gòu)造方法。
2、Scala類的構(gòu)造器包括:主構(gòu)造器和輔助構(gòu)造器
1)基本語法
class 類名(形參列表) { // 主構(gòu)造器
// 類體
def this(形參列表) { // 輔助構(gòu)造器
}
def this(形參列表) { //輔助構(gòu)造器可以有多個...
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
說明:
1、輔助構(gòu)造器,函數(shù)的名稱this,可以有多個,編譯器通過參數(shù)的個數(shù)及類型來區(qū)分。
2、輔助構(gòu)造方法不能直接構(gòu)建對象,必須直接或者間接調(diào)用主構(gòu)造方法。
3、構(gòu)造器調(diào)用其他另外的構(gòu)造器,要求被調(diào)用構(gòu)造器必須提前聲明。
2)案例實操
1、如果主構(gòu)造器無參數(shù),小括號可省略,構(gòu)建對象時調(diào)用的構(gòu)造方法的小括號也可以省略。
//(1)如果主構(gòu)造器無參數(shù),小括號可省略 //class Person (){ class Person { var name: String = _ var age: Int = _ def this(age: Int) { this() this.age = age println("輔助構(gòu)造器") } def this(age: Int, name: String) { this(age) this.name = name } println("主構(gòu)造器") } object Person { def main(args: Array[String]): Unit = { val person2 = new Person(18) } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
6.3.5 構(gòu)造器參數(shù)
1)說明
Scala類的主構(gòu)造器函數(shù)的形參包括三種類型:未用任何修飾、var修飾、val修飾
1、未用任何修飾符修飾,這個參數(shù)就是一個局部變量
2、var修飾參數(shù),作為類的成員屬性使用,可以修改
3、val修飾參數(shù),作為類只讀屬性使用,不能修改
2)案例實操
class Person(name: String, var age: Int, val sex: String) {
}
object Test {
def main(args: Array[String]): Unit = {
var person = new Person("bobo", 18, "男")
// (1)未用任何修飾符修飾,這個參數(shù)就是一個局部變量
// printf(person.name)
// (2)var 修飾參數(shù),作為類的成員屬性使用,可以修改
person.age = 19
println(person.age)
// (3)val 修飾參數(shù),作為類的只讀屬性使用,不能修改
// person.sex = "女"
println(person.sex)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
6.4 繼承與多態(tài)
1)基于語法
class 子類名 extends 父類名 {類體}
- 1
1、子類繼承父類的屬性和方法
2、scala是單繼承
2)案例實操
1、子類繼承父類的屬性和方法
2、繼承的調(diào)用順序:父類構(gòu)造器 -> 子類構(gòu)造器
class Person(nameParam: String) { var name = nameParam var age: Int = _ def this(nameParam: String, ageParam: Int) { this(nameParam) this.age = ageParam println("父類輔助構(gòu)造器") } println("父類主構(gòu)造器") } class Emp(nameParam: String, ageParam: Int) extends Person(nameParam, ageParam) { var empNo: Int = _ def this(nameParam: String, ageParam: Int, empNoParam: Int) { this(nameParam, ageParam) this.empNo = empNoParam println("子類的輔助構(gòu)造器") } println("子類主構(gòu)造器") } object Test { def main(args: Array[String]): Unit = { new Emp("z3", 11,1001) } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
3)動態(tài)綁定
Scala中屬性和方法都是動態(tài)綁定,而Java中只有方法為動態(tài)綁定。
案例實操(對比Java和Scala的重寫)
Scala
class Person { val name: String = "person" def hello(): Unit = { println("hello person") } } class Teacher extends Person { override val name: String = "teacher" override def hello(): Unit = { println("hello teacher") } } object Test { def main(args: Array[String]): Unit = { val teacher: Teacher = new Teacher() println(teacher.name) teacher.hello() val teacher1:Person = new Teacher println(teacher1.name) teacher1.hello() } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
Java
class Person { public String name = "person"; public void hello() { System.out.println("hello person"); } } class Teacher extends Person { public String name = "teacher"; @Override public void hello() { System.out.println("hello teacher"); } } public class TestDynamic { public static void main(String[] args) { Teacher teacher = new Teacher(); Person teacher1 = new Teacher(); System.out.println(teacher.name); teacher.hello(); System.out.println(teacher1.name); teacher1.hello(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
結(jié)果對比
6.5 抽象類
6.5.1 抽象屬性和抽象方法
1)基于語法
1、定義抽象類:abstract class Person{} //通過abstract關鍵字標記抽象類
2、定義抽象屬性:val | var name: String //一個屬性沒有初始化,就是抽象屬性
3、定義抽象方法:def hello();String //只聲明而沒有實現(xiàn)的方法,就是抽象方法
案例實操
abstract class Person {
val name: String
def hello(): Unit
}
class Teacher extends Person {
val name: String = "teacher"
def hello(): Unit = {
println("hello teacher")
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2)繼承&重寫
1、如果父類為抽象類,那么子類需要將抽象的屬性和方法實現(xiàn),否則子類也需要聲明為抽象類。
2、重寫非抽象方法需要用override修飾,重寫抽象方法則可以不加override。
3、子類中調(diào)用父類的方法使用super關鍵字
4、子類對抽象屬性進行實現(xiàn),父類抽象屬性可以用var修飾;子類對非抽象屬性重寫,父類非抽象屬性只支持val類型,而不支持var;因為var修飾的為可變變量,子類繼承之后就可以直接使用,沒有必要重寫。
6.5.2 匿名子類
1)說明:
和Java一樣,可以通過包含帶有定義或重寫的代碼塊的方式創(chuàng)建一個匿名的子類。
2)案例實操
abstract class Person {
val name: String
def hello(): Unit
}
object Test {
def main(args: Array[String]): Unit = {
val person = new Person {
override val name: String = "teacher"
override def hello(): Unit = println("hello teacher")
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
6.6 單例對象(伴生對象)
Scala語言是完全面向?qū)ο蟮恼Z言,所以并沒有靜態(tài)的操作(即在Scala中沒有靜態(tài)的概念)。但是為了能夠和Java語言交互(因為Java中有靜態(tài)概念),就產(chǎn)生了一種特殊的對象來模擬類對象,該對象為單例對象。若單例對象名與類名一致,則稱該單例對象為這個類的伴生對象,這個類的所有”靜態(tài)“內(nèi)容都可以放置在它的伴生對象中聲明。
6.6.1 單例對象語法
1)基本語法
object Person{
val country: String = "China"
}
- 1
- 2
- 3
2)說明
1、單例對象采用object關鍵字聲明
2、單例對象對應的類稱之為伴生類,伴生對象的名稱應該和伴生類名一致。
3、單例對象中的屬性和方法都可以通過伴生對象名(類名)直接調(diào)用訪問。
3)案例實操
//(1)伴生對象采用 object 關鍵字聲明
object Person {
var country: String = "China"
}
//(2)伴生對象對應的類稱之為伴生類,伴生對象的名稱應該和伴生類名一致。
class Person {
var name: String = "bobo"
}
object Test {
def main(args: Array[String]): Unit = {
//(3)伴生對象中的屬性和方法都可以通過伴生對象名(類名)直接調(diào)用訪問。
println(Person.country)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
6.6.2 apply方法
1)說明
1、通過伴生對象的apply方法,實現(xiàn)不使用new方法創(chuàng)建對象
2、如果想讓主構(gòu)造器變成私有的,可以在()之前加上private。
3、apply方法可以重載
4、Scala中obj(arg)的語句實際是在調(diào)用該對象的apply方法,即obj.apply(arg)。用以統(tǒng)一面向?qū)ο缶幊毯秃瘮?shù)式編程的風格。
5、當使用new關鍵字構(gòu)建對象時,調(diào)用的其實是類的構(gòu)造方法,當直接使用類名構(gòu)建對象時,調(diào)用的其實是伴生對象的apply方法。
2)案例實操
object Test {
def main(args: Array[String]): Unit = {
//(1)通過伴生對象的 apply 方法,實現(xiàn)不使用 new 關鍵字創(chuàng)建對象。
val p1 = Person()
println("p1.name=" + p1.name)
val p2 = Person("bobo")
println("p2.name=" + p2.name)
}
}
//(2)如果想讓主構(gòu)造器變成私有的,可以在()之前加上 private
class Person private(cName: String) {
var name: String = cName
}
object Person {
def apply(): Person = {
println("apply 空參被調(diào)用")
new Person("xx")
}
def apply(name: String): Person = {
println("apply 有參被調(diào)用")
new Person(name)
//注意:也可以創(chuàng)建其它類型對象,并不一定是伴生類對象
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
擴展:在Scala中實現(xiàn)單例模式
6.7 特質(zhì)(Trait)
1、Scala語言中,采用特質(zhì)trait(特征)來代替接口的概念,也就是說,多個類具有相同的特質(zhì)(特征)時,就可以將這個特質(zhì)(特征)獨立出來,采用關鍵字trait聲明。
2、Scala中的trait中即可以有抽象屬性和方法,也可以有具體的屬性和方法,一個類可以混入(mixin)多個特質(zhì),這種感覺類似于Java中的抽象類。
3、Scala引入trait特征,第一可以替代Java的接口,第二個也是對單繼承機制的一種補充。
6.7.1 特質(zhì)聲明
1)基本語法
trait 特質(zhì)名{
trait 主體
}
- 1
- 2
- 3
2)案例實操
trait PersonTrait {
// 聲明屬性
var name:String = _
// 聲明方法
def eat():Unit={
}
// 抽象屬性
var age:Int
// 抽象方法
def say():Unit
}
//通過查看字節(jié)碼,可以看到特質(zhì)=抽象類+接口
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
6.7.2 特質(zhì)基本語法
一個類具有某種特質(zhì)(特征),就意味著這個類滿足了這個特質(zhì)(特征)的所有要素,所以在使用時,也采用了extends關鍵字,如果有多個特質(zhì)或存在父類,那么需要采用with關鍵字連接。
1)基本語法
1、沒有父類:class 類名 extends 特質(zhì)1 with 特質(zhì)2 with 特質(zhì)3 ...
2、有父類:class 類名 extends 父類 with 特質(zhì)1 with 特質(zhì)2 with 特質(zhì)3...
- 1
- 2
2)說明
1、類和特質(zhì)的關系:使用繼承的關系。
2、當一個類去繼承特質(zhì)時,第一個連接詞是extends,后面是with。
3、如果一個類在同時繼承特質(zhì)和父類時,應當把父類寫在extends后。
3)案例實操
1、特質(zhì)可以同時擁有抽象方法和具體方法
2、一個類可以混入(mixin)多個特質(zhì)
3、所有的Java接口都可以當做Scala特質(zhì)使用
4、動態(tài)混入:可靈活的擴展類的功能
4.1 動態(tài)混入:創(chuàng)建對象時混入trait,而無需使類混入該trait
4.2 如果混入的trait中有未實現(xiàn)的方法,則需要實現(xiàn)。
trait PersonTrait { //(1)特質(zhì)可以同時擁有抽象方法和具體方法 // 聲明屬性 var name: String = _ // 抽象屬性 var age: Int // 聲明方法 def eat(): Unit = { println("eat") } // 抽象方法 def say(): Unit } trait SexTrait { var sex: String } //(2)一個類可以實現(xiàn)/繼承多個特質(zhì) //(3)所有的 Java 接口都可以當做 Scala 特質(zhì)使用 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)動態(tài)混入:可靈活的擴展類的功能 val t2 = new Teacher with SexTrait { override var sex: String = "男" } //調(diào)用混入 trait 的屬性 println(t2.sex) } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
6.7.3 特質(zhì)疊加
由于一個類可以混入(mixin)多個trait,且trait中可以有具體的屬性和方法,若混入的特質(zhì)中具有相同的方法(方法名,參數(shù)列表,返回值均相同),必然會出現(xiàn)繼承沖突問題。沖突分為以下兩種:
第一種,一個類(Sub)混入的兩個trait(TraitA ,TraitB)中具有相同的具體方法,且兩個trait之間沒有任何關系,解決這類沖突問題,直接在類(Sub)中重寫沖突方法。
第二種,一個類(Sub)混入的兩個trait(TraitA,TraitB)中具有相同的具體方法,且兩個trait繼承自相同的trait(TraitC),及所謂的“鉆石問題”,解決這類沖突問題,Scala采用了特質(zhì)疊加的策略。
所謂的特質(zhì)疊加,就是將混入的多個trait中的沖突方法疊加起來,案例如下:
trait Ball { def describe(): String = { "ball" } } trait Color extends Ball { override def describe(): String = { "blue-" + super.describe() } } trait Category extends Ball { override def describe(): String = { "foot-" + super.describe() } } class MyBall extends Category with Color { override def describe(): String = { "my ball is a " + super.describe() } } object TestTrait { def main(args: Array[String]): Unit = { println(new MyBall().describe()) } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
結(jié)果如下:
6.7.4 特質(zhì)疊加執(zhí)行順序
思考:上述案例中的super.describe()調(diào)用的是父trait中的方法嗎?
當一個類混入多個特質(zhì)的時候,scala會對所有的特質(zhì)及其父特質(zhì)按照一定的順序進行排序,而此案例中的supr.describe()調(diào)用的實際上是排好序后的下一個特質(zhì)中的describe()方法,排序規(guī)則如下:
結(jié)論:
1、案例中的super不是表示其父特質(zhì)對象,而是表示上述疊加書匈奴中的下一個特質(zhì),即,MyClass中的super指代Color,Color中的super指代Category,Category中的super指代Ball。
2、如果想要調(diào)用某個指定的混入特質(zhì)中的方法,可以增加約束:super[],例如super[Category].describe()。
6.7.5 特質(zhì)自身類型
1)說明
自身類型可實現(xiàn)依賴注入的功能。
2)案例實操
class User(val name: String, val age: Int) trait Dao { def insert(user: User) = { println("insert into database :" + user.name) } } trait APP { _: Dao => def login(user: User): Unit = { println("login :" + user.name) insert(user) } } object MyApp extends APP with Dao { def main(args: Array[String]): Unit = { login(new User("bobo", 11)) } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
6.7.6 特質(zhì)和抽象類的區(qū)別
1、優(yōu)先使用特質(zhì)。一個類擴展多個特質(zhì)是很方便的,但卻只能擴展一個抽象類。
2、如果你需要構(gòu)造函數(shù)參數(shù),使用抽象類。因為抽象類可以定義帶參數(shù)的構(gòu)造函數(shù),而特質(zhì)不行(有無參構(gòu)造)。
6.8 擴展
6.8.1 類型檢查和轉(zhuǎn)換
1)說明
(1)obj.isInstanceOf[T]:判斷 obj 是不是 T 類型。
(2)obj.asInstanceOf[T]:將 obj 強轉(zhuǎn)成 T 類型。
(3)classOf 獲取對象的類名。
2)案例實操
class Person{ } object Person { def main(args: Array[String]): Unit = { val person = new Person //(1)判斷對象是否為某個類型的實例 val bool: Boolean = person.isInstanceOf[Person] if ( bool ) { //(2)將對象轉(zhuǎn)換為某個類型的實例 val p1: Person = person.asInstanceOf[Person] println(p1) } //(3)獲取類的信息 val pClass: Class[Person] = classOf[Person] println(pClass) } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
6.8.2 枚舉類和應用類
1)說明
枚舉類:需要繼承Enumeration
應用類:需要繼承App
2)案例實操
object Test {
def main(args: Array[String]): Unit = {
println(Color.RED)
}
}
// 枚舉類
object Color extends Enumeration {
val RED = Value(1, "red")
val YELLOW = Value(2, "yellow")
val BLUE = Value(3, "blue")
}
// 應用類
object Test20 extends App {
println("xxxxxxxxxxx");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
6.8.3 Type定義新類型
1)說明
使用type關鍵字可以定義新的數(shù)據(jù)類型名稱,本質(zhì)上就是類型的一個別名。
2)案例實操
object Test {
def main(args: Array[String]): Unit = {
type S=String
var v:S="abc"
def test():S="xyz"
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
下一章(第七章) 集合
1、 Scala的面向?qū)ο笏枷牒蚃ava的面向?qū)ο笏枷牒透拍钍且恢碌摹?br> 2、Scala中語法和Java不同,補充了更多的功能。
6.1 Scala包
1)基本語法
package 包名
- 1
2)Scala包的三大作用(和Java一樣)
1、區(qū)分相同名字的類
2、當類很多時,可以很好的管理類
3、控制訪問范圍
6.1.1 包的命名
1)命名規(guī)則
只能包含數(shù)字、字母、下劃線、小圓點,但不能用數(shù)字開頭,也不要使用關鍵字。
2)案例實操
demo.class.execl //錯誤,因為class關鍵字
demo.12a //錯誤,數(shù)字開頭
- 1
- 2
3)命名規(guī)范
一般是小寫字母 + 小圓點
com.公司名.項目名.業(yè)務模塊名
4)案例實操
com.itcast.oa.model
com.itcast.oa.controller
com.sohu.bank.order
- 1
- 2
- 3
6.1.2 包說明(包語句)
1)說明
Scala有兩種包的管理風格,一種方式和Java的包管理風格相同,每個源文件一個包(包名和源文件所在路徑不要求必須一致),包名用 “.” 進行分隔以表示包的層級關系,如com.atguigu.scala。另一種風格,通過嵌套的風格表示層級關系,如下
package com{
package atguigu{
package scala{
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
第二種風格有以下特點:
(1)一個源文件中可以聲明多個package
(2)子包中的類可以直接訪問父包中的內(nèi)容,而無需導包
2)案例實操
package com {
import com.atguigu.Inner //父包訪問子包需要導包
object Outer {
val out: String = "out"
def main(args: Array[String]): Unit = {
println(Inner.in)
}
}
package atguigu {
object Inner {
val in: String = "in"
def main(args: Array[String]): Unit = {
println(Outer.out) //子包訪問父包無需導包
}
}
}
}
package other {
}
到了這里,關于Scala(第六章 面向?qū)ο螅┑奈恼戮徒榻B完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!