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) 

本文主要参考自Scala School-基础知识(续)

Scala学习(二)——高级特性的更多相关文章

  1. 大数据笔记(二十六)——Scala语言的高级特性

    ===================== Scala语言的高级特性 ========================一.Scala的集合 1.可变集合mutable 不可变集合immutable / ...

  2. Scala学习(二)--- 控制结构和函数

    控制结构和函数 摘要: 本篇主要学习在Scala中使用条件表达式.循环和函数,你会看到Scala和其他编程语言之间一个根本性的差异.在Java或C++中,我们把表达式(比如3+4)和语句(比如if语句 ...

  3. Scala学习二——控制结构和函数

    一.if表达式有值 val s=if(x>0) 1 else -1,相当于Java中x>0?1:-1(不过不拿呢个在?:中插入语句),而且Scala中可以用混合类型(如if (x>0 ...

  4. php面向对象编程学习之高级特性

    前几天写了一篇关于php面向对象基础知识的博客,这两天看了php面向对象的高级特性,写出来记录一下吧,方便以后拿出来复习. 面向对象除了最基本的定义类之外,最主要就是因为面向的一些高级特性,运用这些高 ...

  5. Scala学习——函数高级操作

    scala函数高级操作 一.字符串高级操作 多行字符串和插值 package top.ruandb.scala.Course06 object StringApp { def main(args: A ...

  6. Scala学习二十二——定界延续

    一.本章要点 延续让你可以回到程序执行当中之前的某个点; 可以在shift块中捕获延续 延续函数一直延展到包含它的reset块的尾部 延续所谓的”余下的运算“,从包含shift的表达式开始,到包含它的 ...

  7. Scala学习二十一——隐式转换和隐式参数

    一.本章要点 隐式转换用于类型之间的转换 必须引入隐式转换,并确保它们可以以单个标识符的形式出现在当前作用域 隐式参数列表会要求指定类型的对象.它们可以从当前作用域中以单个标识符定义的隐式对象的获取, ...

  8. Scala学习二十——Actor

    一.本章要点 每个actor都要扩展Actor类并提供act方法 要往actor发送消息,可以用actor!message 消息发送是异步的:”发完就忘“ 要接受消息,actor可以调用receive ...

  9. Scala学习(二)练习

    Scala控制结构和函数&练习 1. 一个数字如果为正数,则它的signum为1:如果是负数,则signum为-1:如果为0,则signum为0:编写一个函数来计算这个值 简单逻辑判断: 测试 ...

  10. Python学习之高级特性

    切片 在Python基础篇里,我们知道Python的可序列对象可以通过索引号(下标)来引用对象元素,索引号可以由0开始从左向右依次获取,可以从-1开始由右向左获取.这种方法可以帮助我们依次获取我们想要 ...

随机推荐

  1. 第一篇 jQuery

    1-1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. ...

  2. 启动web项目报错:The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone.

    解决: 在application.properties配置文件中的添加标红部分 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/miaosha?se ...

  3. linux下NVIDIA GPU驱动安装最简方式

    之前一节已经写到了,上次的GPU driver驱动安装并不成功,因此,这次换了一种方式,比较傻瓜,但是很好使. 首先使用命令查看显示器的设备(请将显示器插在显卡上,如果插在集显上可能信息不正常) su ...

  4. 神经网络优化算法:梯度下降法、Momentum、RMSprop和Adam

    最近回顾神经网络的知识,简单做一些整理,归档一下神经网络优化算法的知识.关于神经网络的优化,吴恩达的深度学习课程讲解得非常通俗易懂,有需要的可以去学习一下,本人只是对课程知识点做一个总结.吴恩达的深度 ...

  5. linux的一些运维操作基本知识

    1 ~/.bashrc 这个可以认为是linux系统的启动项,每次启动的时候都会运行一些这里边的命令: 常见的有: alias rm='rm -i'//修改某些指令: export LD_LIBRAR ...

  6. Dubbo 03 Restful风格的API

    目录 Dubbo03 restful风格的API 根路径 协议 版本 用HTTP协议里的动词来实现资源的增删改查 用例 swagger(丝袜哥) OpenAPI 资源 编写API文档 整合Spring ...

  7. [HDU 3521] [最小割] Being a Hero

    题意: 在一个有向图中,有n个点,m条边$n \le 1000 \And \And  m \le 100000$ 每条边有一个破坏的花费,有些点可以被选择并获得对应的金币. 假设一个可以选的点是$x$ ...

  8. 关于join

  9. [转帖]微軟将从 .NET 4 以后的版本弃用 System.Data.OracleClient

    转帖--微軟将从 .NET 4 以后的版本弃用 System.Data.OracleClient Posted on -- : eaglet 阅读() 评论() 编辑 收藏 原贴 http://www ...

  10. Ajax异步传值总结

    Ajax异步传值 将数据从前台传向后台: 1:通过get方式,将参数在链接中,配合“?”进行传值. 实例: //前台传值方法 //触发该方法调用ajax function testAjax(yourD ...