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方法—结束”)
}
}
- 返回值是函数的函数
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的函数实现)
正常定义:
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)
}
}
- 偏应用函数实现(向某人问好)
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(列表)
- 概念说明
- 类似于数组,要求所有元素的类型都相同,通过范型来约束
- 列表是不可变集合,一旦定义了就不能改变
- 列表具有递归定义的性质,可以嵌套定义,这是与数组最大的不一样。
- 应用示例
- 列表初始化
- 概念说明
- 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))
}
- 用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丰富程度不一样
- 不可变Map
- 常用操作
- 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代码实现子父类继承关系。