博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scala学习(二)——高级特性
阅读量:4582 次
发布时间:2019-06-09

本文共 3641 字,大约阅读时间需要 12 分钟。

apply() 方法

apply方法是Scala提供的一个语法糖

  • 类名+括号,调用对象的apply方法 

  • 对象名+括号,调用类的apply方法

对apply方法的简单测试:(其中,带 new -- class ApplyTest,不带 new -- object ApplyTest)

class ApplyTest {
println("class ApplyTest")
def apply() {
println("class APPLY method")
}
}
object ApplyTest {
println("object ApplyTest")
def apply() = {
println("object APPLY method")
new ApplyTest()
}
}
 
// 对象名+括号,调用类的apply方法
val a1 = new ApplyTest()
a1() // == a1.apply()
// 输出 class ApplyTest, class APPLY method
 
// 类名+括号,调用对象的apply方法
val a2 = ApplyTest()
// 输出 object ApplyTest, object APPLY method, class ApplyTest
 
val a2 = ApplyTest()
a2()
// 输出 object ApplyTest, object APPLY method, class ApplyTest, class APPLY method
 
val a3 = ApplyTest
// 输出 object ApplyTest
 
val a3 = ApplyTest
a3()
// 输出 object ApplyTest, object APPLY method, class ApplyTest

 

单例对象

单例对象用于持有一个类的唯一实例。通常用于工厂模式。

object Timer {
var count = 0
def currentCount(): Long = {
count += 1
count
}
}

可以这样使用:

Timer.currentCount() //1

单例对象可以和类具有相同的名称,此时该对象也被称为“伴生对象”。我们通常将伴生对象作为工厂使用。

下面是一个简单的例子,可以不需要使用’new’来创建一个实例了。

class Bar(foo: String)
object Bar {
def apply(foo: String) = new Bar(foo)
}

 

函数即对象

在Scala中,我们经常谈论对象的函数式编程。这是什么意思?到底什么是函数呢?

函数是一些特质的集合。具体来说,具有一个参数的函数是Function1特质的一个实例。这个特质定义了apply()语法糖,让你调用一个对象时就像你在调用一个函数。

object addOne extends Function1[Int, Int] {
def apply(m: Int): Int = m + 1
}
addOne(1) // 2

这个Function特质集合下标从0开始一直到22。为什么是22?这是一个主观的魔幻数字(magic number)。我从来没有使用过多于22个参数的函数,所以这个数字似乎是合理的。

apply语法糖有助于统一对象和函数式编程的二重性。你可以传递类,并把它们当做函数使用,而函数本质上是类的实例。

这是否意味着,当你在类中定义一个方法时,得到的实际上是一个Function*的实例?不是的,在类中定义的方法是方法而不是函数。在repl中独立定义的方法是Function*的实例。

类也可以扩展Function,这些类的实例可以使用()调用。

class AddOne extends Function1[Int, Int] {
def apply(m: Int): Int = m + 1
}
val plusOne = new AddOne()
plusOne(1) //2

可以使用更直观快捷的extends (Int => Int)代替extends Function1[Int, Int]

class AddOne extends (Int => Int) {
def apply(m: Int): Int = m + 1
}

 

模式匹配

这是Scala中最有用的部分之一。

匹配值

val times = 1
times match {
case 1 => "one"
case 2 => "two"
case _ => "some other number"
}

使用守卫进行匹配

times match {
case i if i == 1 => "one"
case i if i == 2 => "two"
case _ => "some other number"
}

注意我们是怎样获取变量’i’的值的。

在最后一行指令中的_是一个通配符;它保证了我们可以处理所有的情况。 否则当传进一个不能被匹配的数字的时候,你将获得一个运行时错误。

匹配类型

你可以使用 match来分别处理不同类型的值。

def bigger(o: Any): Any = {
o match {
case i: Int if i < 0 => i - 1
case i: Int => i + 1
case d: Double if d < 0.0 => d - 0.1
case d: Double => d + 0.1
case text: String => text + "s"
}
}

匹配类成员

定义一个计算器,让我们通过类型对它们进行分类。

def calcType(calc: Calculator) = calc match {
case _ if calc.brand == "HP" && calc.model == "20B" => "financial"
case _ if calc.brand == "HP" && calc.model == "48G" => "scientific"
case _ if calc.brand == "HP" && calc.model == "30B" => "business"
case _ => "unknown"
}

 

样本类 Case Classes

使用样本类可以方便得存储和匹配类的内容。不用new关键字就可以创建它们。

case class Calculator(brand: String, model: String)
val hp20b = Calculator("HP", "20b")

样本类基于构造函数的参数,自动地实现了相等性和易读的toString方法。

val hp20b = Calculator("HP", "20b")
val hp20B = Calculator("HP", "20b")
hp20b == hp20B // true

样本类也可以像普通类那样拥有方法。

使用样本类进行模式匹配

样本类就是被设计用在模式匹配中的。让我们简化之前的计算器分类器的例子。

val hp20b = Calculator("HP", "20B")
val hp30b = Calculator("HP", "30B")
def calcType(calc: Calculator) = calc match {
case Calculator("HP", "20B") => "financial"
case Calculator("HP", "48G") => "scientific"
case Calculator("HP", "30B") => "business"
case Calculator(ourBrand, ourModel) => "Calculator: %s %s is of unknown type".format(ourBrand, ourModel)
}

最后一句也可以这样写

case Calculator(_, _) => "Calculator of unknown type"

或者我们完全可以不将匹配对象指定为Calculator类型

case _ => "Calculator of unknown type"

或者我们也可以将匹配的值重新命名。

case c@Calculator(_, _) => "Calculator: %s of unknown type".format(c)

 

本文主要参考自

转载于:https://www.cnblogs.com/wmx24/p/9362717.html

你可能感兴趣的文章
sublime长期使用的快捷键
查看>>
calendar模块
查看>>
Java正则表达式示例
查看>>
Sketch教程
查看>>
29.奖金(拓扑排序)
查看>>
HTML5 中的拖放
查看>>
javascript 学习总结第二天
查看>>
「OC」点语法和成员变量的作用域
查看>>
thinkphp知识点
查看>>
对各种lca算法的理解
查看>>
[delphi]保证程序只运行一个实例
查看>>
java学习之语句结构
查看>>
python打包exe文件-ImportError: No module named 'queue'
查看>>
Memcache限制端口和访问IP
查看>>
IP通信基础 3.18
查看>>
【转】:ZooKeeper真不是最终一致性的,而是顺序一致性
查看>>
JSON Web Token in ASP.NET Web API 2 using Owin
查看>>
python安装.whl文件失败
查看>>
servlet的转发与重定向
查看>>
除了ROS, 机器人定位导航还有其他方案吗?
查看>>