240511Scala笔记
第5章 函数式编程
5.1函数式编程
函数式编程:
1)面向对象编程
解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。
对象:用户
行为:登录、连接 JDBC、读取数据库
属性:用户名、密码
Scala 语言是一个完全面向对象编程语言。万物皆对象
对象的本质:对数据和行为的一个封装
2)函数式编程
解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用
这些封装好的步骤,解决问题。
例如:请求->用户名、密码->连接 JDBC->读取数据库
Scala 语言是一个完全函数式编程语言。万物皆函数。
函数的本质:函数可以当做一个值进行传递
3)在 Scala 中函数式编程和面向对象编程完美融合在一起了。
5.1 函数基础
5.1.1 函数基本语法
1)基本语法
2)案例实操
需求:定义一个函数,实现将传入的名称打印出来。
object TestFunction {
def main(args: Array[String]): Unit = {
// (1)函数定义
def f(arg: String): Unit = {
println(arg)
}
// (2)函数调用
// 函数名(参数)
f("hello world")
}
}
5.1.2 函数和方法的区别
1)核心概念
(1)为完成某一功能的程序语句的集合,称为函数。
(2)类中的函数称之方法。
2)案例实操
(1)Scala 语言可以在任何的语法结构中声明任何的语法
(2)函数没有重载和重写的概念;方法可以进行重载和重写
(3)Scala 中函数可以嵌套定义
object TestFunction {
// (2)方法可以进行重载和重写,程序可以执行
def main(): Unit = {
}
def main(args: Array[String]): Unit = {
// (1)Scala 语言可以在任何的语法结构中声明任何的语法
import java.util.Date
new Date()
// (2)函数没有重载和重写的概念,程序报错
def test(): Unit ={
println("无参,无返回值")
}
test()
def test(name:String):Unit={
println()
}
//(3)Scala 中函数可以嵌套定义
def test2(): Unit ={
def test3(name:String):Unit={
println("函数可以嵌套定义")
}
}
}
}
5.1.3 函数定义
1)函数定义
(1)函数 1:无参,无返回值
(2)函数 2:无参,有返回值
(3)函数 3:有参,无返回值
(4)函数 4:有参,有返回值
(5)函数 5:多参,无返回值
(6)函数 6:多参,有返回值
2)案例实操
package chapter05
object Test02_FunctionDefine {
def main(args: Array[String]): Unit = {
// (1)函数1:无参,无返回值
def f1(): Unit = {
println("1. 无参,无返回值")
}
f1()
println(f1())
println("=========================")
// (2)函数2:无参,有返回值
def f2(): Int = {
println("2. 无参,有返回值")
return 12
}
println(f2())
println("=========================")
// (3)函数3:有参,无返回值
def f3(name: String): Unit = {
println("3:有参,无返回值 " + name)
}
println(f3("alice"))
println("=========================")
// (4)函数4:有参,有返回值
def f4(name: String): String = {
println("4:有参,有返回值 " + name)
return "hi, " + name
}
println(f4("alice"))
println("=========================")
// (5)函数5:多参,无返回值
def f5(name1: String, name2: String): Unit = {
println("5:多参,无返回值")
println(s"${name1}和${name2}都是我的好朋友")
}
f5("alice","bob")
println("=========================")
// (6)函数6:多参,有返回值
def f6(a: Int, b: Int): Int = {
println("6:多参,有返回值")
return a + b
}
println(f6(12, 37))
}
}
5.1.2.什么是面向对象,什么是面向过程?
面向对象:类似于盖浇饭,做到饭菜分离,可以通过组合不同的步骤
面向过程:类似于炒饭,都是把饭搅匀炒着吃,一气呵成
文心一言AI的说明:
面向对象和面向过程是两种不同的编程范式,它们在处理问题和设计程序时有着明显的区别。以下是它们之间的主要区别:
-
关注点:
-
面向过程:主要关注解决问题的步骤,即算法的实现。它将问题分解成一系列的函数或过程,并依次调用这些函数或过程来解决问题。
-
面向对象:主要关注问题的本质,即对象及其之间的关系。它将问题分解成一系列的对象,并通过对象之间的交互来解决问题。
-
-
代码复用性:
-
面向过程:代码复用性较低。由于它主要关注解决问题的步骤,因此相同的代码段可能需要在不同的地方重复编写。
-
面向对象:代码复用性较高。通过继承和组合等机制,可以轻松地重用已有的代码。
-
-
扩展性:
-
面向过程:扩展性较差。由于它主要关注具体的步骤实现,因此当需要添加新功能或修改现有功能时,可能需要修改大量的代码。
-
面向对象:扩展性较好。由于它主要关注对象及其之间的关系,因此当需要添加新功能或修改现有功能时,通常只需要修改相应的对象即可。
-
-
抽象程度:
-
面向过程:抽象程度较低。它主要关注具体的步骤实现,因此代码中的细节较多。
-
面向对象:抽象程度较高。它主要关注问题的本质和对象之间的关系,因此可以将问题抽象成更高级别的概念。
-
-
设计复杂性:
-
面向过程:设计复杂性较低。由于它主要关注具体的步骤实现,因此设计过程相对简单。
-
面向对象:设计复杂性较高。由于它主要关注对象及其之间的关系,因此需要更多的思考和设计来确保对象之间的交互和协作能够正确地实现。
-
-
适用场景:
-
面向过程:适用于简单的问题或算法实现,以及需要高效率的场景(如底层开发、游戏开发等)。
-
面向对象:适用于复杂的问题或系统,需要高抽象性和可扩展性的场景(如大型软件开发、企业级应用等)。
-
总的来说,面向对象和面向过程各有优缺点,适用于不同的场景和需求。在选择使用哪种编程范式时,需要根据具体情况进行权衡和选择。
5.1.3.什么是函数式编程
函数式编程是一种编程范式,主要思想是将计算机运算看作函数的计算。它强调程序的执行结果而非执行过程,通过一系列嵌套的函数调用来实现运算过程。函数式编程中,函数是"第一等公民",它们可以与变量一样,被赋值给其他变量,作为参数传入函数,或者作为其他函数的返回值。
函数式编程的主要特性包括:
-
闭包和高阶函数:函数式编程支持函数作为第一类对象,这些函数可以像对象一样被操作。高阶函数则是指可以接受其他函数作为参数或返回函数的函数。
-
惰性计算:在惰性计算中,表达式不是在绑定到变量时立即计算,而是在需要其值时进行计算。这允许编写可能产生无穷输出的函数,而无需担心内存溢出问题。
-
递归:函数式编程经常使用递归作为控制流程的机制,尤其是在处理列表或树形结构时。
-
无副作用:函数式编程中的函数不应产生除运算结果以外的其他影响,即函数的运行不应依赖于或改变外部状态。
-
不可变性:在函数式编程中,变量通常是不可变的,即它们的值在初始化后不能被修改。如果需要改变值,通常会创建一个新的变量。
-
引用透明:函数的运行应仅依赖于其输入参数,而与外部状态或变量无关。
函数式编程的例子包括LISP、Haskell、Clean、Erlang和Miranda等语言。这种编程范式在并发编程、数据处理和科学计算等领域具有广泛应用。
5.1.4 函数参数
1)案例实操
(1)可变参数
(2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
(3)参数默认值,一般将有默认值的参数放置在参数列表的后面
(4)带名参数
package chapter05
object Test03_FunctionParameter {
def main(args: Array[String]): Unit = {
// (1)可变参数
def f1(str: String*): Unit = {
println(str)
}
f1("alice")
f1("aaa", "bbb", "ccc")
// (2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
def f2(str1: String, str2: String*): Unit = {
println("str1: " + str1 + " str2: " + str2)
}
f2("alice")
f2("aaa", "bbb", "ccc")
// (3)参数默认值,一般将有默认值的参数放置在参数列表的后面
def f3(name: String = "atguigu"): Unit = {
println("My school is " + name)
}
f3("school")
f3()
// (4)带名参数
def f4(name: String = "atguigu", age: Int): Unit = {
println(s"${age}岁的${name}在尚硅谷学习")
}
f4("alice", 20)
f4(age = 23, name = "bob")
f4(age = 21)
}
}
5.1.5 函数至简原则(重点)
函数至简原则:能省则省
1)至简原则细节
(1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
(2)如果函数体只有一行代码,可以省略花括号
(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
(4)如果有 return,则不能省略返回值类型,必须指定
(5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
(6)Scala 如果期望是无返回值类型,可以省略等号
(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
2)案例实操
package chapter05
// 函数至简原则
object Test04_Simplify {
def main(args: Array[String]): Unit = {
def f0(name: String): String = {
return name
}
println(f0("atguigu"))
println("==========================")
// (1)return可以省略,Scala会使用函数体的最后一行代码作为返回值
def f1(name: String): String = {
name
}
println(f1("atguigu"))
println("==========================")
// (2)如果函数体只有一行代码,可以省略花括号
def f2(name: String): String = name
println(f2("atguigu"))
println("==========================")
// (3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
def f3(name: String) = name
println(f3("atguigu"))
println("==========================")
// (4)如果有return,则不能省略返回值类型,必须指定
// def f4(name: String) = {
// return name
// }
//
// println(f4("atguigu"))
println("==========================")
// (5)如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
def f5(name: String): Unit = {
return name
}
println(f5("atguigu"))
println("==========================")
// (6)Scala如果期望是无返回值类型,可以省略等号
def f6(name: String) {
println(name)
}
println(f6("atguigu"))
println("==========================")
// (7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
def f7(): Unit = {
println("atguigu")
}
f7()
f7
println("==========================")
// (8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
def f8: Unit = {
println("atguigu")
}
// f8()
f8
println("==========================")
// (9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
def f9(name: String): Unit = {
println(name)
}
// 匿名函数,lambda表达式
(name: String) => { println(name) }
println("==========================")
}
}
5.1.6匿名函数
package chapter05
object Test05_Lambda {
def main(args: Array[String]): Unit = {
val fun = (name: String) => {
println(name)
}
fun("atguigu")
println("========================")
// 定义一个函数,以函数作为参数输入
def f(func: String => Unit): Unit = {
func("atguigu")
}
f(fun)
f((name: String) => {
println(name)
})
println("========================")
// 匿名函数的简化原则
// (1)参数的类型可以省略,会根据形参进行自动的推导
f((name) => {
println(name)
})
// (2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。
f( name => {
println(name)
})
// (3)匿名函数如果只有一行,则大括号也可以省略
f( name => println(name) )
// (4)如果参数只出现一次,则参数省略且后面参数可以用_代替
f( println(_) )
// (5) 如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线
f( println )
println("=========================")
// 实际示例,定义一个”二元运算“函数,只操作1和2两个数,但是具体运算通过参数传入
def dualFunctionOneAndTwo(fun: (Int, Int)=>Int): Int = {
fun(1, 2)
}
val add = (a: Int, b: Int) => a + b
val minus = (a: Int, b: Int) => a - b
println(dualFunctionOneAndTwo(add))
println(dualFunctionOneAndTwo(minus))
// 匿名函数简化
println(dualFunctionOneAndTwo((a: Int, b: Int) => a + b))
println(dualFunctionOneAndTwo((a: Int, b: Int) => a - b))
println(dualFunctionOneAndTwo((a, b) => a + b))
println(dualFunctionOneAndTwo( _ + _))
println(dualFunctionOneAndTwo( _ - _))
println(dualFunctionOneAndTwo((a, b) => b - a))
println(dualFunctionOneAndTwo( -_ + _))
}
}
5.2 高级函数
5.2.1 高阶函数
函数的高阶用法:
package chapter05
object Test06_HighOrderFunction {
def main(args: Array[String]): Unit = {
def f(n: Int): Int = {
println("f调用")
n + 1
}
def fun(): Int = {
println("fun调用")
1
}
val result: Int = f(123)
println(result)
// 1. 函数作为值进行传递
val f1: Int=>Int = f
val f2 = f _
println(f1)
println(f1(12))
println(f2)
println(f2(35))
val f3: ()=>Int = fun
val f4 = fun _
println(f3)
println(f4)
// 2. 函数作为参数进行传递
// 定义二元计算函数
def dualEval(op: (Int, Int)=>Int, a: Int, b: Int): Int = {
op(a, b)
}
def add(a: Int, b: Int): Int = {
a + b
}
println(dualEval(add, 12, 35))
println(dualEval((a, b) => a + b, 12, 35))
println(dualEval(_ + _, 12, 35))
// 3. 函数作为函数的返回值返回
def f5(): Int=>Unit = {
def f6(a: Int): Unit = {
println("f6调用 " + a)
}
f6 // 将函数直接返回
}
// val f6 = f5()
// println(f6)
// println(f6(25))
println(f5()(25))
}
}
5.2.2 高阶函数2
关于yield的使用
val array = Array(1, 2, 3, 4, 5)
val squared = for (elem <- array) yield elem * elem // 平方每个元素
// squared 现在是 Vector(1, 4, 9, 16, 25)
println(squared)
// 如果你想要一个List而不是Vector
val squaredList = (for (elem <- array) yield elem * elem).toList
println(squaredList) // List(1, 4, 9, 16, 25)
高阶函数(数组):
package chapter05
object Test07_Practice_CollectionOperation {
def main(args: Array[String]): Unit = {
val arr: Array[Int] = Array(12, 45, 75, 98)
// 对数组进行处理,将操作抽象出来,处理完毕之后的结果返回一个新的数组
def arrayOperation(array: Array[Int], op: Int=>Int): Array[Int] = {
for (elem <- array) yield op(elem)
}
// 定义一个加一操作
def addOne(elem: Int): Int = {
elem + 1
}
// 调用函数
val newArray: Array[Int] = arrayOperation(arr, addOne)
println(newArray.mkString(","))
// 传入匿名函数,实现元素翻倍
val newArray2 = arrayOperation(arr, _ * 2)
//val newArray2 = arrayOperation(arr, elem => el* 2)
println(newArray2.mkString(", "))
}
}
5.2.3 高阶函数练习
package chapter05
object Test08_Practice {
def main(args: Array[String]): Unit = {
// 1. 练习1
val fun = (i: Int, s: String, c: Char) => {
if (i == 0 && s == "" && c == '0') false else true
}
println(fun(0, "", '0'))
println(fun(0, "", '1'))
println(fun(23, "", '0'))
println(fun(0, "hello", '0'))
println("===========================")
// 2. 练习2
def func(i: Int): String=>(Char=>Boolean) = {
def f1(s: String): Char=>Boolean = {
def f2(c: Char): Boolean = {
if (i == 0 && s == "" && c == '0') false else true
}
f2
}
f1
}
println(func(0)("")('0'))
println(func(0)("")('1'))
println(func(23)("")('0'))
println(func(0)("hello")('0'))
// 匿名函数简写
def func1(i: Int): String=>(Char=>Boolean) = {
s => c => if (i == 0 && s == "" && c == '0') false else true
}
println(func1(0)("")('0'))
println(func1(0)("")('1'))
println(func1(23)("")('0'))
println(func1(0)("hello")('0'))
// 柯里化
def func2(i: Int)(s: String)(c: Char): Boolean = {
if (i == 0 && s == "" && c == '0') false else true
}
println(func2(0)("")('0'))
println(func2(0)("")('1'))
println(func2(23)("")('0'))
println(func2(0)("hello")('0'))
}
}
5.2.4 柯里化和闭包
package chapter05
object Test09_ClosureAndCurrying {
def main(args: Array[String]): Unit = {
def add(a: Int, b: Int): Int = {
a + b
}
// 1. 考虑固定一个加数的场景
def addByFour(b: Int): Int = {
4 + b
}
// 2. 扩展固定加数改变的情况
def addByFive(b: Int): Int = {
5 + b
}
// 3. 将固定加数作为另一个参数传入,但是是作为”第一层参数“传入
def addByFour1(): Int=>Int = {
val a = 4
def addB(b: Int): Int = {
a + b
}
addB
}
def addByA(a: Int): Int=>Int = {
def addB(b: Int): Int = {
a + b
}
addB
}
println(addByA(35)(24))
val addByFour2 = addByA(4)
val addByFive2 = addByA(5)
println(addByFour2(13))
println(addByFive2(25))
// 4. lambda表达式简写
def addByA1(a: Int): Int=>Int = {
(b: Int) => {
a + b
}
}
def addByA2(a: Int): Int=>Int = {
b => a + b
}
def addByA3(a: Int): Int=>Int = a + _
val addByFour3 = addByA3(4)
val addByFive3 = addByA3(5)
println(addByFour3(13))
println(addByFive3(25))
// 5. 柯里化
def addCurrying(a: Int)(b: Int): Int = {
a + b
}
println(addCurrying(35)(24))
}
}
5.2.5 递归
package chapter05
import scala.annotation.tailrec
object Test10_Recursion {
def main(args: Array[String]): Unit = {
println(fact(5))
println(tailFact(5))
}
// 递归实现计算阶乘
def fact(n: Int): Int = {
if (n == 0) return 1
fact(n - 1) * n
}
// 尾递归实现
def tailFact(n: Int): Int = {
@tailrec
def loop(n: Int, currRes: Int): Int = {
if (n == 0) return currRes
loop(n - 1, currRes * n)
}
loop(n, 1)
}
}
5.2.6控制抽象
package chapter05
object Test11_ControlAbstraction {
def main(args: Array[String]): Unit = {
// 1. 传值参数
def f0(a: Int): Unit = {
println("a: " + a)
println("a: " + a)
}
f0(23)
def f1(): Int = {
println("f1调用")
12
}
f0(f1())
println("========================")
// 2. 传名参数,传递的不再是具体的值,而是代码块
def f2(a: =>Int): Unit = {
println("a: " + a)
println("a: " + a)
}
f2(23)
f2(f1())
f2({
println("这是一个代码块")
29
})
}
}
2.控制抽象练习
package chapter05
object Test12_MyWhile {
def main(args: Array[String]): Unit = {
var n = 10
// 1. 常规的while循环
while (n >= 1){
println(n)
n -= 1
}
// 2. 用闭包实现一个函数,将代码块作为参数传入,递归调用
def myWhile(condition: =>Boolean): (=>Unit)=>Unit = {
// 内层函数需要递归调用,参数就是循环体
def doLoop(op: =>Unit): Unit = {
if (condition){
op
myWhile(condition)(op)
}
}
doLoop _
}
println("=================")
n = 10
myWhile(n >= 1){
println(n)
n -= 1
}
// 3. 用匿名函数实现
def myWhile2(condition: =>Boolean): (=>Unit)=>Unit = {
// 内层函数需要递归调用,参数就是循环体
op => {
if (condition){
op
myWhile2(condition)(op)
}
}
}
println("=================")
n = 10
myWhile2(n >= 1){
println(n)
n -= 1
}
// 3. 用柯里化实现
def myWhile3(condition: =>Boolean)(op: =>Unit): Unit = {
if (condition){
op
myWhile3(condition)(op)
}
}
println("=================")
n = 10
myWhile3(n >= 1){
println(n)
n -= 1
}
}
}
5.2.6 惰性函数(懒加载)
package chapter05
object Test13_Lazy {
def main(args: Array[String]): Unit = {
lazy val result: Int = sum(13, 47)
println("1. 函数调用")
println("2. result = " + result)
println("4. result = " + result)
}
def sum(a: Int, b: Int): Int = {
println("3. sum调用")
a + b
}
}
第6章 面向对象
6.1 scala类
6.1.1 包的命名
package com{
import com.atguigu.scala.Inner
// 在外层包中定义单例对象
object Outer{
var out: String = "out"
def main(args: Array[String]): Unit = {
println(Inner.in)
}
}
package atguigu{
package scala{
// 内层包中定义单例对象
object Inner{
var in: String = "in"
def main(args: Array[String]): Unit = {
println(Outer.out)
Outer.out = "outer"
println(Outer.out)
}
}
}
}
}
// 在同一文件中定义不同的包
package aaa{
package bbb{
object Test01_Package{
def main(args: Array[String]): Unit = {
import com.atguigu.scala.Inner
println(Inner.in)
}
}
}
}
6.1.2 包说明(包语句)
6.1.3 包对象
package object chapter06 {
val commonValue = "Yello River"
def commonMethod() = {
println(s"我们在${commonValue}学习")
}
}
6.1.4 导包说明
6.2 类和对象
6.2.1 定义类
package chapter06
import scala.beans.BeanProperty
object Test03_Class {
def main(args: Array[String]): Unit = {
// 创建一个对象
val student = new Student()
// student.name // error, 不能访问private属性
println(student.age)
println(student.sex)
student.sex = "female"
println(student.sex)
}
}
// 定义一个类
class Student {
// 定义属性
private var name: String = "alice"
@BeanProperty
var age: Int = _
var sex: String = _
}
6.2.2 属性
6.3 封装
6.1.1 封装
Access:
package chapter06
object Test04_Access {
def main(args: Array[String]): Unit = {
// 创建对象
val person: Person = new Person()
// person.idCard // error
// person.name // error
println(person.age)
println(person.sex)
person.printInfo()
var worker: Worker = new Worker()
// worker = new Worker()
// worker.age = 23
worker.printInfo()
}
}
// 定义一个子类
class Worker extends Person {
override def printInfo(): Unit = {
// println(idCard) // error
name = "bob"
age = 25
sex = "male"
println(s"Worker: $name $sex $age")
}
}
ClassForAccess:
package chapter06
object Test04_ClassForAccess {
}
// 定义一个父类
class Person {
private var idCard: String = "3523566"
protected var name: String = "alice"
var sex: String = "female"
private[chapter06] var age: Int = 18
def printInfo(): Unit = {
println(s"Person: $idCard $name $sex $age")
}
}
class Worker extends Perison{} #里面的extends是继承的意思,Worker继承Persion
override def printInfo(): Unit = {} #里的override是重写的意思,重写printInfo方法
6.2.5 构造器
构造方法1:
package chapter06
object Test05_Constructor {
def main(args: Array[String]): Unit = {
val student1 = new Student1
student1.Student1()
val student2 = new Student1("alice")
val student3 = new Student1("bob", 25)
}
}
// 定义一个类
class Student1() {
// 定义属性
var name: String = _
var age: Int = _
println("1. 主构造方法被调用")
// 声明辅助构造方法
def this(name: String) {
this() // 直接调用主构造器
println("2. 辅助构造方法一被调用")
this.name = name
println(s"name: $name age: $age")
}
def this(name: String, age: Int){
this(name)
println("3. 辅助构造方法二被调用")
this.age = age
println(s"name: $name age: $age")
}
def Student1(): Unit = {
println("一般方法被调用")
}
}
构造方法2:
package chapter06
object Test05_Constructor {
def main(args: Array[String]): Unit = {
val student1 = new Student1
student1.Student1()
val student2 = new Student1("alice")
val student3 = new Student1("bob", 25)
}
}
// 定义一个类
class Student1() {
// 定义属性
var name: String = _
var age: Int = _
println("1. 主构造方法被调用")
// 声明辅助构造方法
def this(name: String) {
this() // 直接调用主构造器
println("2. 辅助构造方法一被调用")
this.name = name
println(s"name: $name age: $age")
}
def this(name: String, age: Int){
this(name)
println("3. 辅助构造方法二被调用")
this.age = age
println(s"name: $name age: $age")
}
def Student1(): Unit = {
println("一般方法被调用")
}
}
构造器1:
package chapter06
object Test06_ConstructorParams {
def main(args: Array[String]): Unit = {
val student2 = new Student2
student2.name = "alice"
student2.age = 18
println(s"student2: name = ${student2.name}, age = ${student2.age}")
val student3 = new Student3("bob", 20)
println(s"student3: name = ${student3.name}, age = ${student3.age}")
val student4 = new Student4("cary", 25)
// println(s"student4: name = ${student4.name}, age = ${student4.age}")
student4.printInfo()
val student5 = new Student5("bob", 20)
println(s"student3: name = ${student5.name}, age = ${student5.age}")
student3.age = 21
val student6 = new Student6("cary", 25, "atguigu")
println(s"student6: name = ${student6.name}, age = ${student6.age}")
student6.printInfo()
}
}
// 定义类
// 无参构造器
class Student2 {
// 单独定义属性
var name: String = _
var age: Int = _
}
// 上面定义等价于
class Student3(var name: String, var age: Int)
// 主构造器参数无修饰
class Student4(name: String, age: Int){
def printInfo(){
println(s"student4: name = ${name}, age = $age")
}
}
//class Student4(_name: String, _age: Int){
// var name: String = _name
// var age: Int = _age
//}
class Student5(val name: String, val age: Int)
class Student6(var name: String, var age: Int){
var school: String = _
def this(name: String, age: Int, school: String){
this(name, age)
this.school = school
}
def printInfo(){
println(s"student6: name = ${name}, age = $age, school = $school")
}
}
6.4.1 继承和多态
继承和多态1:
package chapter06
object Test07_Inherit {
def main(args: Array[String]): Unit = {
val student1: Student7 = new Student7("alice", 18)
val student2 = new Student7("bob", 20, "std001")
student1.printInfo()
student2.printInfo()
val teacher = new Teacher
teacher.printInfo()
def personInfo(person: Person7): Unit = {
person.printInfo()
}
println("=========================")
val person = new Person7
personInfo(student1)
personInfo(teacher)
personInfo(person)
}
}
// 定义一个父类
class Person7() {
var name: String = _
var age: Int = _
println("1. 父类的主构造器调用")
def this(name: String, age: Int){
this()
println("2. 父类的辅助构造器调用")
this.name = name
this.age = age
}
def printInfo(): Unit = {
println(s"Person: $name $age")
}
}
// 定义子类
class Student7(name: String, age: Int) extends Person7(name, age) {
var stdNo: String = _
println("3. 子类的主构造器调用")
def this(name: String, age: Int, stdNo: String){
this(name, age)
println("4. 子类的辅助构造器调用")
this.stdNo = stdNo
}
override def printInfo(): Unit = {
println(s"Student: $name $age $stdNo")
}
}
class Teacher extends Person7 {
override def printInfo(): Unit = {
println(s"Teacher")
}
}
继承和多态2:
package chapter06
object Test08_DynamicBind {
def main(args: Array[String]): Unit = {
val student: Person8 = new Student8
println(student.name)
student.hello()
}
}
class Person8 {
val name: String = "person"
def hello(): Unit = {
println("hello person")
}
}
class Student8 extends Person8 {
override val name: String = "student"
override def hello(): Unit = {
println("hello student")
}
}
6.5 抽象类
6.5.1 抽象属性和方法
package chapter06
object Test09_AbstractClass {
def main(args: Array[String]): Unit = {
val student = new Student9
student.eat()
student.sleep()
}
}
// 定义抽象类
abstract class Person9{
// 非抽象属性
var name: String = "person"
// 抽象属性
var age: Int
// 非抽象方法
def eat(): Unit = {
println("person eat")
}
// 抽象方法
def sleep(): Unit
}
// 定义具体的实现子类
class Student9 extends Person9 {
// 实现抽象属性和方法
var age: Int = 18
def sleep(): Unit = {
println("student sleep")
}
// 重写非抽象属性和方法
// override val name: String = "student"
name = "student"
override def eat(): Unit = {
super.eat()
println("student eat")
}
}
6.5.2 匿名子类
package chapter06
object Test10_AnnoymousClass {
def main(args: Array[String]): Unit = {
val person: Person10 = new Person10 {
override var name: String = "alice"
override def eat(): Unit = println("person eat")
}
println(person.name)
person.eat()
}
}
// 定义抽象类
abstract class Person10 {
var name: String
def eat(): Unit
}
6.6 单例对象(伴生对象)
6.6.1 单例对象
package chapter06
object Test11_Object {
def main(args: Array[String]): Unit = {
// val student = new Student11("alice", 18)
// student.printInfo()
val student1 = Student11.newStudent("alice", 18)
student1.printInfo()
val student2 = Student11.apply("bob", 19)
student2.printInfo()
val student3 = Student11("bob", 19)
student3.printInfo()
}
}
// 定义类
class Student11 private(val name: String, val age: Int){
def printInfo(){
println(s"student: name = ${name}, age = $age, school = ${Student11.school}")
}
}
// 伴生对象
object Student11{
val school: String = "atguigu"
// 定义一个类的对象实例的创建方法
def newStudent(name: String, age: Int): Student11 = new Student11(name, age)
def apply(name: String, age: Int): Student11 = new Student11(name, age)
}
6.2.2 单例设计模式
package chapter06
object Test12_Singleton {
def main(args: Array[String]): Unit = {
val student1 = Student12.getInstance()
student1.printInfo()
val student2 = Student12.getInstance()
student2.printInfo()
println(student1)
println(student2)
}
}
class Student12 private(val name: String, val age: Int){
def printInfo(){
println(s"student: name = ${name}, age = $age, school = ${Student11.school}")
}
}
// 饿汉式
//object Student12 {
// private val student: Student12 = new Student12("alice", 18)
// def getInstance(): Student12 = student
//}
// 懒汉式
object Student12 {
private var student: Student12 = _
def getInstance(): Student12 = {
if (student == null){
// 如果没有对象实例的话,就创建一个
student = new Student12("alice", 18)
}
student
}
}
6.2.3 特质#Test13
package chapter06
object Test13_Trait {
def main(args: Array[String]): Unit = {
val student: Student13 = new Student13
student.sayHello()
student.study()
student.dating()
student.play()
}
}
// 定义一个父类
class Person13 {
val name: String = "person"
var age: Int = 18
def sayHello(): Unit = {
println("hello from: " + name)
}
def increase(): Unit = {
println("person increase")
}
}
// 定义一个特质
trait Young {
// 声明抽象和非抽象属性
var age: Int
val name: String = "young"
// 声明抽象和非抽象的方法
def play(): Unit = {
println(s"young people $name is playing")
}
def dating(): Unit
}
class Student13 extends Person13 with Young {
// 重写冲突的属性
override val name: String = "student"
// 实现抽象方法
def dating(): Unit = println(s"student $name is dating")
def study(): Unit = println(s"student $name is studying")
// 重写父类方法
override def sayHello(): Unit = {
super.sayHello()
println(s"hello from: student $name")
}
}
6.2.4 特质的混入#Test14
package chapter06
object Test14_TraitMixin {
def main(args: Array[String]): Unit = {
val student = new Student14
student.study()
student.increase()
student.play()
student.increase()
student.dating()
student.increase()
println("===========================")
// 动态混入
val studentWithTalent = new Student14 with Talent {
override def dancing(): Unit = println("student is good at dancing")
override def singing(): Unit = println("student is good at singing")
}
studentWithTalent.sayHello()
studentWithTalent.play()
studentWithTalent.study()
studentWithTalent.dating()
studentWithTalent.dancing()
studentWithTalent.singing()
}
}
// 再定义一个特质
trait Knowledge {
var amount: Int = 0
def increase(): Unit
}
trait Talent {
def singing(): Unit
def dancing(): Unit
}
class Student14 extends Person13 with Young with Knowledge {
// 重写冲突的属性
override val name: String = "student"
// 实现抽象方法
def dating(): Unit = println(s"student $name is dating")
def study(): Unit = println(s"student $name is studying")
// 重写父类方法
override def sayHello(): Unit = {
super.sayHello()
println(s"hello from: student $name")
}
// 实现特质中的抽象方法
override def increase(): Unit = {
amount += 1
println(s"student $name knowledge increased: $amount")
}
}
6.2.5 #Test15
package chapter06
object Test15_TraitOverlying {
def main(args: Array[String]): Unit = {
val student = new Student15
student.increase()
//钻石问题特征叠加
val myFootBall = new MyFootBall
println(myFootBall.describe())
}
}
trait Knowledge15{
var amount: Int = 0
def increase():Unit ={
println("knowledge increased")
}
}
//定义球类特征
trait Ball{
def describe():String = "ball"
}
trait ColorBall extends Ball{
var color : String = "red"
}
trait CategoryBall extends Ball{
var category : String = "foot"
override def describe(): String = category+"-"+super.describe()
}
// 定义一个自定义球的类
class MyFootBall extends CategoryBall with ColorBall{
override def describe(): String = "my ball is a "+super[CategoryBall].describe()
}
trait Talent15{
def singing():Unit
def dancing():Unit
def increase(): Unit = {
println("talent increased")
}
}
class Student15 extends Person13 with Talent15 with Knowledge15{
override def dancing(): Unit = println("dancing")
override def singing(): Unit = println("singing")
override def increase(): Unit = {
super[Person13].increase()
}
}
6.2.6 #Test16
package chapter06
object Test16_TraitSelfType {
def main(args: Array[String]): Unit = {
val user = new RegisterUser("alice", "123456")
user.insert()
}
}
// 用户类
class User(val name: String, val password: String)
trait UserDao {
_: User =>
// 向数据库插入数据
def insert(): Unit = {
println(s"insert into db: ${this.name}")
}
}
// 定义注册用户类
class RegisterUser(name: String, password: String) extends User(name, password) with UserDao
6.2.7 #Test17_Textends
package chapter06
object Test17_Extends {
def main(args: Array[String]): Unit = {
// 1. 类型的检测和转换
val student: Student17 = new Student17("alice", 18)
student.study()
student.sayHi()
val person: Person17 = new Student17("bob", 20)
person.sayHi()
// 类型判断
println("student is Student17: " + student.isInstanceOf[Student17])
println("student is Person17: " + student.isInstanceOf[Person17])
println("person is Person17: " + person.isInstanceOf[Person17])
println("person is Student: " + person.isInstanceOf[Student17])
val person2: Person17 = new Person17("cary", 35)
println("person2 is Student17: " + person2.isInstanceOf[Student17])
// 类型转换
if (person.isInstanceOf[Student17]){
val newStudent = person.asInstanceOf[Student17]
newStudent.study()
}
println(classOf[Student17])
// 2. 测试枚举类
println(WorkDay.MONDAY)
}
}
class Person17(val name: String, val age: Int){
def sayHi(): Unit = {
println("hi from person " + name)
}
}
class Student17(name: String, age: Int) extends Person17(name, age){
override def sayHi(): Unit = {
println("hi from student " + name)
}
def study(): Unit = {
println("student study")
}
}
// 定义枚举类对象
object WorkDay extends Enumeration {
val MONDAY = Value(1, "Monday")
val TUESDAY = Value(2, "TuesDay")
}
// 定义应用类对象
object TestApp extends App {
println("app start")
type MyString = String
val a: MyString = "abc"
println(a)
}