Scala进阶篇

1、函数高级应用

主要包含10种函数高级应用,
包括 1) 函数传名调用
2) 指定函数参数名调用
3) 可变参数的函数
4) 默认参数值函数
5) 递归函数
6) 高阶函数
7) 内嵌函数
8) 匿名函数
9) 偏应用函数
10) 函数柯里化

  • 1) 函数传名调用
    • 概念说明
      • 传值调用:先计算参数表达式的值,再应用到函数内部,把=>去掉即可,即按原始的方式
      • 传名调用:将未计算的参数表达式直接应用到函数内部,用=>来设置传名调用
    • 应用示例-传值

object TestCallByValue {
def main(args: Array[String]) {
delayedCalculator(transmitMe());
}
def transmitMe(): String = {
println(“我在transmitMe方法中!”)
return “transmitMe返回值”;
}
def delayedCalculator(t: String): Unit = {
println(“在 delayedCalculator方法—开始”)
println(“正式调用传过来的函数: “ + t)
println(“在 delayedCalculator方法—结束”)
}
}

  • 应用示例-传名

object TestCallByName {
def main(args: Array[String]) {
delayedCalculator(transmitMe());
}
def transmitMe(): String = {
println(“我在transmitMe方法中!”)
return “transmitMe返回值”;
}
def delayedCalculator(t: => String): Unit = {
println(“在 delayedCalculator方法—开始”)
println(“正式调用传过来的函数: “ + t)
println(“在 delayedCalculator方法—结束”)
}
}

  • 2)指定函数参数名调用

object TestCallByParaName {
def main(args: Array[String]) {
printBabyNames(second = “张二”, first = “张一”);
}
def printBabyNames(first: String, second: String): Unit = {
println(“第一个孩子叫=” + first);
println(“第二个孩子叫=” + second);
}
}

  • 3)可变(不定长)参数的函数

object TestNonFixParas {
def main(args: Array[String]) {
printAllParasValue(“one”, “two”, “three”, “four”);
}
def printAllParasValue(paras: String*): Unit = {
for (temp <- paras) {
println(temp);
}
}
}

  • 4)默认参数值函数

object TestDefaultParaFunction {
def main(args: Array[String]) {
println(“完全使用默认值的返回值 : “ + salaryMoney());
println(“部分使用默认值的返回值 : “ + salaryMoney(10));
println(“部分使用默认值的返回值 : “ + salaryMoney(10,10000));
}
def salaryMoney(a: Int = 5, unit: Int = 1000): Int = {
return a * unit
}
}

  • 5)递归函数

object TestRecusive {
def main(args: Array[String]) {
var n=4
println(n+”的阶乘为=”+myFactorial(n))
}
def myFactorial(n: Int): Int = {
if (n <= 1)
return 1
else
return n * myFactorial(n - 1)
}
}

  • 6)高阶函数
    • 概念说明
      • 第一种:将一个函数当做另外一个函数的参数,即参数为函数的函数
      • 第二种:返回值是函数的函数,即高阶函数可以产生函数
    • 应用示例
      • 参数为函数的函数

object TestHighFunctionByTransmitFunctionPara {
def main(args: Array[String]) {
delayedCalculator(transmitMe());
}
def transmitMe(): String = {
println(“我在transmitMe方法中!”)
return “transmitMe返回值”;
}
def delayedCalculator(t: => String): Unit = {
println(“在 delayedCalculator方法—开始”)
println(“正式调用传过来的函数: “ + t)
println(“在 delayedCalculator方法—结束”)
}
}

  1. - 返回值是函数的函数

object TestHighFunctionByRetFunction {
def main(args: Array[String]) {
var mySalaryFun=multiplyBy(1000);
println(mySalaryFun(10));
}
def multiplyBy(salaryUnit:Int)=(x:Int)=>salaryUnit*x
}

  • 7)内嵌函数
    • 概念介绍
      • 函数内定义函数,定义在函数内的函数称之为局部函数,亦称内嵌函数
    • 应用示例

object TestEmbedFunction {
def main(args: Array[String]) {
var msg=”HelloWorld”;
printMessage(msg);
}
def printMessage(msg: String): Unit = {
def printMessageInner(msg: String): Unit = {
println(msg);
}
printMessageInner(msg);
}
}

  • 8)匿名函数
    • 概念介绍
      • 没有函数名称的函数
      • 使代码更简洁,用=>来表示,左侧是参数列表,右侧是函数体
    • 应用示例
      • 匿名用法(使值自增+1的函数实现)

函数定义:
var inc = (x:Int) => x+1
函数使用:
var x = inc(8)+1

  1. - 正常写法(使值自增+1的函数实现)

正常定义:
def incFunction(x: Int): Int = {
return x + 1;
}
函数使用:
var x=incFunction(8)+1

  • 9)偏应用函数
    • 概念说明
      • 不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数
      • 实现方法:绑定函数的一部分参数,非绑定部分用”_”代替,从而形成偏应用函数去使用
    • 应用示例
      • 传统方法实现(向某人问好)

import java.util.Date
object TestPartialParasFunction {
def main(args: Array[String]) {
val name=”张三”
sayHello(name, “上午好”)
Thread.sleep(1000)
sayHello(name, “中午好”)
Thread.sleep(1000)
sayHello(name, “晚上好”)
}
def sayHello(name: String, message: String) = {
println(name + “——“ + message)
}
}

  1. - 偏应用函数实现(向某人问好)

def main(args: Array[String]) {
val name=”张三”
val partialSay=sayHello(name,:_String);
partialSay(“上午好”)
Thread.sleep(1000)
partialSay(“中午好”)
Thread.sleep(1000)
partialSay(“晚上好”)
}
def sayHello(name: String, message: String) = {
println(name + “——“ + message)
}

  • 10) 函数柯里化
    • 概念说明
      • 将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。
      • 提高了使用方法的灵活性
    • 应用举例
      • 传统实现add方法定义

def add(x: Int, y: Int) = x + y;

  • 传统实现add方法使用

def main(args: Array[String]) {
println(add(3,4));
}
def add(x: Int, y: Int) = x + y;

  • 柯里化实现add方法定义

def add(x:Int)(y:Int) = x + y

  • 柯里化实现add方法使用

object TestCurryingFunction {
def main(args: Array[String]) {
//对应柯里化形式1的使用
var curryingAdd1 = add1(3)
//对应柯里化形式2的使用
var curryingAdd2 = add2(3)(_)

println(curryingAdd1(4));
println(curryingAdd2(4));
}
//柯里化形式1
def add1(x: Int) = (y: Int) => x + y;
//柯里化形式2
def add2(x: Int)(y: Int) = x + y;
}

2、集合collection

  • 概念说明

    • 该集合与Java中的集合类似,只是scala重新实现了自身的集合抽象
    • 分为可变集合和不可变集合
    • 常用集合列表 | 序号 | 集合类 | 说明 | | —- | —- | —- | | 1 | Scala List(列表) | 元素以线性方式存储,集合中可以存放重复对象。 | | 2 | Scala Set(集合) | 集合中的对象不按特定的方式排序,并且没有重复对象。 | | 3 | Scala Map(映射) | KV对存储 | | 4 | Scala 元组 | 元组是不同类型的值的集合 | | 5 | Scala Option | 表示有可能包含值的容器,也可能不包含值。 | | 6 | Scala Iterator迭代器 | 迭代器不是一个容器,更确切的说是逐一访问容器内元素的方法 |
  • 应用示例

    • Scala List(列表)
      • 概念说明
        • 类似于数组,要求所有元素的类型都相同,通过范型来约束
        • 列表是不可变集合,一旦定义了就不能改变
        • 列表具有递归定义的性质,可以嵌套定义,这是与数组最大的不一样。
      • 应用示例
        • 列表初始化

def main(args: Array[String]) {
// 字符串列表
val language: List[String] = List(“java”, “python”, “c++”)
// 整型列表
val nums: List[Int] = List(1, 2, 3, 4)
// 空列表
val empty: List[Nothing] = List()
// 二维列表
val dim: List[List[Int]] =
List(
List(1, 0, 0),
List(0, 1, 0),
List(0, 0, 1))
}

  1. - Nil和::来构建列表

def main(args: Array[String]) {
// 字符串列表
val language= “java” :: (“python” :: (“c++” :: Nil))
// 整型列表
val nums = 1 :: (2 :: (3 :: (4 :: Nil)))
// 空列表
val empty = Nil
// 二维列表
val dim = (1 :: (0 :: (0 :: Nil))) ::
(0 :: (1 :: (0 :: Nil))) ::
(0 :: (0 :: (1 :: Nil))) :: Nil

  • 常用操作
    • head 返回列表第一个元素
    • tail 返回一个列表,包含除了第一元素之外的其他元素
    • isEmpty 在列表为空时返回true
    • ::: 运算符或 List.:::() 方法或 List.concat() 方法来连接两个或多个列表
    • List.fill() 方法来创建一个指定重复数量的元素列表
    • List.tabulate() 方法是通过给定的函数来创建列表。
    • List.reverse 用于将列表的顺序反转
  • 应用示例

object TestListFunction {
def main(args: Array[String]) {
val language1 = “java” :: (“python” :: (“c++” :: Nil))
val nums = Nil
/
基本操作
/
println(“基本操作————“);
println(“第一语言是 : “ + language1.head)
println(“除第1个语言之外的其它语言是 : “ + language1.tail)
println(“查看列表 language1是否为空 : “ + language1.isEmpty)
println(“查看 nums 是否为空 : “ + nums.isEmpty)
/

列表连接
/
println(“列表连接————“);
val language2 = “c” :: (“php” :: (“go” :: Nil))
// 使用 ::: 运算符
var mainLanguages = language1 ::: language2
println(“language1 ::: language2 : “ + mainLanguages)
// 使用 List.:::() 方法
mainLanguages = language1.:::(language2)
println(“language1.:::(language2) : “ + mainLanguages)
// 使用 concat 方法
mainLanguages = List.concat(language1, language2)
println(“List.concat(language1, language2) : “ + mainLanguages)
/
fill填充列表的重复元素
/
println(“List fill————“);
val bestLanguage = List.fill(3)(“php”) // 重复 php 3次
println(“bestLanguage : “ + bestLanguage)
val num = List.fill(10)(“php”) // 重复元素 “php”, 10 次
println(“num : “ + num)
/

List tabulate通过给定的函数来创建列表
/
println(“List tabulate————“);
// 通过给定的函数创建 6 个元素
val squares = List.tabulate(6)(n => n n)
println(“一维 : “ + squares)
// 创建二维列表
val mul = List.tabulate(4, 5)(_
_)
println(“多维 : “ + mul)
/*
List.reverse用于将列表的顺序反转
*/
println(“List.reverse————“);
println(mainLanguages.reverse);
}
}

  • Scala Set(集合)

    • 概念说明
      • 没有重复的对象集合,所有的元素都是唯一的
      • Set集合分为可变的和不可变的集合
      • 默认使用不可变集合,完整类路径为:scala.collection.immutable.Set
      • 若要引用可变集合类型,则类路径为:scala.collection.mutable.Set
    • 基础应用示例
      • 不可变集合使用

    def main(args: Array[String]): Unit = {
    //初始化set集合
    val set = Set(1, 2, 3, 4, 5, 6)
    //得到对应的set路径
    println(set.getClass.getName)
    //利用exists方法,判断集合元素中是否存在%2==0的元素
    println(set.exists(_ % 2 == 0))
    //打印当前集合序列
    println(set)
    }

  • 可变集合使用

    def main(args: Array[String]): Unit = {
    //初始化set集合
    val mutableSet = Set(1, 2, 3, 4, 5, 6)
    //获取可变集合的set路径
    println(mutableSet.getClass.getName)
    //添加元素
    mutableSet.add(4)
    println(“添加元素4后=”+mutableSet)
    //删除元素
    mutableSet.remove(1)
    println(“删除元素1后=”+mutableSet)
    mutableSet += 7
    println(“+7后”+mutableSet)
    mutableSet -= 2
    println(“-2后”+mutableSet)

    //将可变set转换成不可变set
    val another = mutableSet.toSet
    println(another.getClass.getName) // scala.collection.immutable.Set
    }

  • 常用操作

    • head 返回集合第一个元素
    • tail 返回一个集合,包含除了第一元素之外的其他元素
    • isEmpty 在集合为空时返回true
    • 使用 ++ 运算符或 Set.++() 方法来连接两个集合
    • 使用 Set.min 方法来查找集合中的最小元素,使用 Set.max 方法查找集合中的最大元素
    • 使用 Set.& 方法或 Set.intersect 方法来查看两个集合的交集元素。
  • 常见应用示例

def main(args: Array[String]): Unit = {
val languageSet1 = Set(“java”, “python”, “c++”)
val numSet: Set[Int] = Set()
/
基本操作
/
println(“基本操作————“);
println(“第一语言是 : “ + languageSet1.head)
println(“除第1个语言之外的其它语言是 : “ + languageSet1.tail)
println(“查看列表 site 是否为空 : “ + languageSet1.isEmpty)
println(“查看 nums 是否为空 : “ + numSet.isEmpty)
/

集合连接操作
/
println(“集合连接————“);
val languageSet2 = Set(“c”, “php”, “go”)
// ++ 作为运算符使用
var mainlanguageSet = languageSet1 ++ languageSet2
println(“languageSet1 ++ languageSet2 : “ + mainlanguageSet)
// ++ 作为方法使用
mainlanguageSet = languageSet1.++(languageSet2)
println(“languageSet1.++(languageSet2) : “ + mainlanguageSet)
/
求集合最大、最小元素
/
println(“求集合最大和最小元素————“);
println(“mainlanguageSet集合中的最小元素是 : “ + mainlanguageSet.min)
println(“mainlanguageSet集合中的最大元素是 : “ + mainlanguageSet.max)
/

求交集
/
println(“求集合的交集————“)
var secondLanguageSet=Set(“shell”,”perl”,”java”)
println(“mainlanguageSet.&(secondLanguageSet) : “ + mainlanguageSet.&(secondLanguageSet))
println(“mainlanguageSet.intersect(secondLanguageSet) : “ + mainlanguageSet.intersect(secondLanguageSet))
}

  • Scala Map(映射)

    • 概念说明
      • 一种可迭代的键值对(key/value)结构,也称为哈希表
      • 所有的值都可以通过键来获取,键值是唯一的
      • 两种类型,可变与不可变,区别在于可变对象可以修改它,而不可变对象不可以
      • 默认使用的不可变 Map,可变的Map需要使用import scala.collection.mutable.Map
    • 基础示例

    def main(args: Array[String]): Unit = {
    // 不可变空Map,键为字符串,值为整型
    var personMap: Map[String, String] = Map()
    // 不可变初始化
    val languageMap = Map(“java” -> “java程序设计”, “python” -> “python程序设计”, “c++” -> “c++程序设计”)
    //动态向不可变map中添加值
    personMap += (“001” -> “张三”)
    //languageMap += (“java” -> “已经理新了”) //此处会报错
    println(personMap)
    println(languageMap)

    //初始化可变Map
    val languageMap2 = scala.collection.mutable.Map(“java” -> “java程序设计”, “python” -> “python程序设计”, “c++” -> “c++程序设计”)
    //向可变Map中添加值
    languageMap2.put(“python”,”已经更新了”)
    println(languageMap2)
    }

  • 关于不可变和可变Map的总结

    • 不可变Map
      • api不太丰富
      • 如果是var修饰,引用可变,支持读写(其内部实现是新new一个map对象进行的新数据的存储)
      • 如果是val修饰,引用不可变,只能写入一次值,其后只读
    • 可变Map
      • api丰富与Java中Map基本类似
      • 如果是var修饰,引用可变,支持读写
      • 如果是val修饰,引用不可变,支持读写
    • 总结
      • 可变与不可变,主要是通过val和var来限定达到意图
      • api丰富程度不一样
  • 常用操作
    • keys:返回 Map 所有的键(key)
    • values:返回 Map 所有的值(value)
    • isEmpty:在 Map 为空时返回true
    • 使用++运算符或Map.++()方法来连接两个Map,Map合并时会移除重复的key。
    • 通过foreach循环输出Map中的keys和values:
    • 使用Map.contains方法来查看Map中是否存在指定的Key
  • 综合示例

    def main(args: Array[String]): Unit = {
    // 不可变空Map,键为字符串,值为整型
    var personMap: Map[String, String] = Map()
    // 不可变初始化
    val languageMap = Map(“java” -> “java程序设计”, “python” -> “python程序设计”, “c++” -> “c++程序设计”)
    /
    基础操作
    /
    println(“基础操作————-“)
    println(“languageMap 中的键为 : “ + languageMap.keys)
    println(“languageMap 中的值为 : “ + languageMap.values)
    println(“检测languageMap是否为空:” + languageMap.isEmpty)
    println(“检测 personMap 是否为空: “ + personMap.isEmpty)
    /

    map合并
    /
    println(“ map合并————-“)
    val languageMap2 = Map(“C” -> “C程序设计”)
    // ++ 作为运算符
    var mainLanguages = languageMap ++ languageMap2
    println(“languageMap ++ languageMap2 : “ + mainLanguages)
    // ++ 作为方法
    mainLanguages = languageMap.++(languageMap2)
    println(“languageMap.++(languageMap2)) : “ + mainLanguages)
    /
    map的keys和values输出
    /
    println(“map的keys和values输出————-“)
    mainLanguages.keys.foreach { key =>
    print(“Key = “ + key)
    println(“ Value = “ + mainLanguages(key))
    }
    /

    查看 Map 中是否存在指定的 Key
    /
    println(“查看 Map 中是否存在指定的 Key————-“)
    if (mainLanguages.contains(“java”)) {
    println(“java键存在,对应的值为 :” + mainLanguages(“java”))
    } else {
    println(“java键不存在”)
    }
    if (mainLanguages.contains(“c#”)) {
    println(“java键存在,对应的值为 :” + mainLanguages(“c#”))
    } else {
    println(“c#键不存在”)
    }
    }

  • Scala 元组

    • 概念说明
      • 与列表相似,元组是不可变的
      • 与列表不同的是,元组可以包含不同类型的元素
      • 元组是通过”( )”来定义的
    • 应用示例

def main(args: Array[String]): Unit = {
//直接定义元组
var personInfo = (“s0001”, “张三”, 21, “河北科技大学”, 1.80)
//通过TupleN来定义,N可以是1至22个可选的元组个数
var pessonInfoTuple5 = new Tuple5(“s0001”, “张三”, 21, “河北科技大学”, 1.80);
/
元组访问,通过元组的索引下标访问,从1开始,元组对象._1代表第1个元素,元组对象._2代表第2个元素,
/
println(“元组访问————-“);
println(“学号=” + personInfo._1);
println(“姓名=” + personInfo._2);
println(“年龄=” + personInfo._3);
println(“学校=” + personInfo._4);
println(“身高=” + personInfo._5);
/

元组遍历
/
println(“元组遍历————-“);
personInfo.productIterator.foreach { ele => println(“元素值 = “ + ele) }
/*
元组转换成字符串
*/
println(“元组转换成字符串 ————-“);
println(personInfo.toString())
}

  • Scala Option[T]

    • 概念说明
      • 表示有可能包含值的容器,也可能不包含值。主要用来表示一个值是可选的
      • Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。
    • 常用方法
      • getOrElse() 方法来获取元组中存在的元素或者使用其默认的值
      • isEmpty() 方法来检测元组中的元素是否为 None
    • 应用示例

    def main(args: Array[String]): Unit = {
    //定义一个map对象
    val mainLanguagesMap = Map(“java” -> “java程序设计”, “python” -> “python程序设计”)
    //通过指定键值,获取可能的value,其返回值是一个Option[T],代表有可能会存在该键值对应的value,也有可能不存在
    var javaDesc: Option[String] = mainLanguagesMap.get(“java”);
    var phpDesc: Option[String] = mainLanguagesMap.get(“php”);
    //打印拿到的结果
    println(“mainLanguagesMap.get(\”java\”) : “ + javaDesc)
    println(“mainLanguagesMap.get(\”php\”) : “ + phpDesc)
    //判断结果是否有值,即是否为None
    println(“javaDesc.isEmpty: “ + javaDesc.isEmpty)
    println(“phpDesc.isEmpty: “ + phpDesc.isEmpty)

    //对拿到的结果做getOrElse操作,即如果不存在该key,则取方法的默认值
    println(“mainLanguagesMap.get(\”java\”) : “ + javaDesc.getOrElse(“没有拿到java的描述信息”))
    println(“mainLanguagesMap.get(\”php\”) : “ + phpDesc.getOrElse(“没有拿到php的描述信息”))
    }

  • Scala Iterator(迭代器)

    • 概念说明
      • 不是一个集合,它是一种用于访问集合的方法。
      • 基本操作是hasNext和next
    • 常用方法或属性
      • it.hasNext() 用于检测集合中是否还有元素。
      • it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态
      • max:取得迭代器对应集合的最大值
      • min:取得迭代器对应集合的最小值
      • size/length:取得迭代器对应集合的长度
    • 应用示例

    def main(args: Array[String]): Unit = {
    val it1 = Iterator(“java”, “python”, “c++”)
    val it2 = Iterator(“java”, “python”, “c++”)
    val it3 = Iterator(“java”, “python”, “c++”)
    val it4 = Iterator(“java”, “python”, “c++”)
    val it5 = Iterator(“java”, “python”, “c++”)

    /
    迭代器遍历集合
    /
    println(“遍历集合————-“);
    while (it1.hasNext) {
    println(it1.next())
    }

    /

    迭代器求集合的最大值
    /
    println(“求迭代器集合的最大值————-“);
    println(it2.max)

    /
    迭代器求集合的最小值
    /
    println(“求迭代器集合的最小值————-“);
    println(it3.min)

    /

    迭代器求集合的长度
    /
    println(“迭代器求集合的长度————-“);
    println(it4.size)
    println(it5.length)
    }

    3、类和对象

  • 概念说明

    • 类和对象通用说明
      • 类是对象的抽象,而对象是类的具体实例。
      • 类是抽象的,不占用内存,而对象是具体的,占用存储空间。
      • 类是用于创建对象的模板,它定义包括在特定类型的对象中的方法和变量。
    • scala类和对象介绍
      • 一个Scala源文件中可以有多个类。
      • 类访问修饰符默认均是public的,并不需要声明
      • 通过new来实例化类,生成相应的对象
      • 类本身是不能作为程序主入口的,必须通过定义Object对象,该对象的main方法作为程序的主入口
  • 应用示例
    • 基础示例

/
主构造方法传参,共三个参数,分别为姓名、性别、年龄
/
class Person(oneName: String, oneGender: String, oneAge: Int) {
//将构造方法传入的局部变量,传递成类的成员变量,方便后续在外部使用使用
var name: String = oneName
var gender: String = oneGender
var age: Int = oneAge
//定义成员方法
def makeMoney(method: String) {
println(“makeMoney method=” + method);
}
}
/

定义一个对象作为程序的运行主类,其main方法作为程序运行的主入口
/
object TestPerson {
def main(args: Array[String]): Unit = {
//通过new实例化Person类的一个对象person
var person = new Person(“张一”, “male”, 20)
//通过对象.属性的方式,获取对象的属性值
println(“person.name=” + person.name)
println(“person.gender=” + person.gender)
println(“person.age=” + person.age)
//通过对象.方法名(参数)的方式,调用方法
person.makeMoney(“coding”)
}
}

  • 类继承
    • 概念说明
      • Scala继承一个基类跟Java很相似,但有若干不同之处。
      • 重写一个非抽象方法必须使用override修饰符
      • 只有主构造函数才可以往基类的构造函数里写参数
      • 在子类中重写父类的抽象方法时,你不需要使用override关键字
    • 应用示例

/
主构造方法传参,共三个参数,分别为姓名、性别、年龄
/
class Person(oneName: String, oneGender: String, oneAge: Int) {
//将构造方法传入的局部变量,传递成类的成员变量,方便后续在外部使用使用
var name: String = oneName
var gender: String = oneGender
var age: Int = oneAge
//定义成员方法
def makeMoney(method: String) {
println(“makeMoney method=” + method);
}
}
/

Student类继承Person类,将相关属性直接传递给父类构造方法
/
class Student(oneStdNo: String, oneName: String, oneGender: String, oneAge: Int) extends Person(oneName, oneGender, oneAge) {
//将新增加构造方法的参数值赋给的成员属性,方便后续在外部使用
var stdNo = oneStdNo;
//重写父类的非抽象成员方法,必须填加override关键字
override def makeMoney(method: String) {
println(“我是个学生,我的学号是” + this.stdNo + “,makeMoney method=” + method);
}
}
/*
定义一个对象作为程序的运行主类,其main方法作为程序运行的主入口
*/
object TestPerson {
def main(args: Array[String]): Unit = {
//通过new实例化Person类的一个对象person
var person = new Student(“s0001”, “张一”, “male”, 20)
//通过对象.属性的方式,获取对象的属性值
println(“person.stdno=” + person.stdNo)
println(“person.name=” + person.name)
println(“person.gender=” + person.gender)
println(“person.age=” + person.age)
//通过对象.方法名(参数)的方式,调用方法
person.makeMoney(“coding”)
}
}

  • 单例模式
    • 概念说明
      • static在scala中是没有的,不符合纯面向对象的模型。
      • scala中使用object关键字来解决单例模式问题。object与类的区别是object不能够带参数。
    • 简单版单例模式

object ChineseSingleton {
var skinColor = “Yellow”
var country = “中国人”
}
object TestSingleton {
def main(args: Array[String]): Unit = {
println(ChineseSingleton.skinColor)
println(ChineseSingleton.country)
ChineseSingleton.skinColor = “黄色”;
println(ChineseSingleton.skinColor)
}
}

  • scala经典版单例模式
    • 概念说明
      • 伴生对象:除了定义的类之外,还要定义一个同名的 object 对象,当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object
      • 伴生类:该伴生对象对应的类,即为伴生类companion class
      • 必须在同一个源文件里定义类和它的伴生对象
      • 类和它的伴生对象可以互相访问其私有成员
    • 应用示例

/
定义伴生类
/
class TaskManager private (oneName: String) {
//将构造方法传入的局部变量,传递成类的成员变量,方便后续在外部使用使用
var name: String = oneName
//定义成员方法
def getName(): String = {
return name;
}
}
/

定义伴生对象
/
object TaskManager {
var taskManager = new TaskManager(“windows任务管理器”);
def getSingletonInstance(): TaskManager = {
return taskManager
}
}
/*
测试单例模式
*/
object TestSingleton {
def main(args: Array[String]): Unit = {
var singleton = TaskManager.getSingletonInstance();
println(singleton.getName());
}
}

4、特质trait

  • 概念说明
    • 相当于Java的接口和抽象类的二合一,即可以当接口使用,也可以像抽象类去定义实际的方法和抽象方法去使用。
    • 特质是支持多继承的,解决了scala单继承的问题,间接达到scala多继承的效果。
    • 用关键字trait来定义特质
  • 应用示例

/*
定义核心计算特征
/
trait CalculateCoreTrait {
def add(a: Int, b: Int): Int = a + b
def minus(a: Int, b: Int): Int = a - b
def factorial(n: Int): Int
}
class TLCalculator(oneName: String) extends CalculateCoreTrait {
var name = oneName
def factorial(n: Int): Int = {
if (n <= 1) {
return 1
} else {
return n
factorial(n - 1)
}
}
}
object TestTrait {
def main(args: Array[String]): Unit = {
var tl: CalculateCoreTrait=new TLCalculator(“晨光计算器”)
var a=3
var b=4
println(“a+b=”+tl.add(a, b))
println(“a-b=”+tl.minus(a, b))
println(“b!=”+tl.factorial(b))
}
}

5、练习题

  • 1、单例模式之懒汉和饿汉模式的java和scala的代码实现。
  • 2、scala代码实现,给定两个Map[String,Integer]的对象、即两个不同班级的成绩单,其中key是人名,value为数学成绩,求两个班级的成绩最高分和最低分?
  • 3、有类Animal,包括属性name、skinColor、high三个属性,其自带2个构造方法,分别是构造方法1(name、skinColor)、构造方法2(name、high)。现有其子类狗Dog,该子类主构造方法继承父类构造方法2。

试用scala代码实现子父类继承关系。