【Scala】Scala之Methods(下)

简介: 前面学习了Scala的Class,下面接着学习Method(方法)。

2.4 调用方法时使用参数名

  1. 问题描述

  当调用方法时,你更喜欢使用参数名

  2. 解决方案

  常用的指定参数来调用方法格式如下

methodName(param1=value1, param2=value2, ...)

 有如下类 

class Pizza {
    var crustSize = 12
    var crustType = "Thin"
    def update(crustSize: Int, crustType: String) {
        this.crustSize = crustSize
        this.crustType = crustType
    }
    override def toString = {
        "A %d inch %s crust pizza.".format(crustSize, crustType)
    }
}

可以使用如下方法调用

p.update(crustSize = 16, crustType = "Thick")
p.update(crustType = "Pan", crustSize = 14)

3. 讨论

  使用参数名调用方法显得冗长,但是具有更好的可读性,当参数类型相同时,其显得尤为有用,可比较如下两种调用 

engage(true, true, true, false) 
engage(speedIsSet = true,
        directionIsSet = true,
        picardSaidMakeItSo = true,
        turnedOffParkingBrake = false)

 显然第二种具有更好的可读性

  2.5 定义返回多项(元组)的方法

  1. 问题描述

  你想要从一个方法中返回多个值,但是你不想将这些值封装在类中

  2. 解决方案

  Scala可以使用tuple,让你从方法中返回多个值,如下返回三元组

def getStockInfo = {
    // other code here ...
    ("NFLX", 100.00, 101.00) // this is a Tuple3
}

然后调用该方法并将返回值赋值给变量 

val (symbol, currentPrice, bidPrice) = getStockInfo

3. 讨论

  在Java中也可以从方法中返回多个值,但是其是将多个值封装在类中而并非使用tuple

  getStockInfo方法返回的是三元组tuple3,tuple最多可以容纳22个变量,即22元组tuple22,如下定义的是二元组

  9.png

  当然也可以直接使用一个val变量来存储方法返回值,然后通过._1、._2符号来访问对应的值

  10.png

  2.6 强制调用者不使用括号调用方法

  1. 问题描述

  你想强调如下编程风格,在调用访问方法时不使用括号

  2. 解决方案

  在定义访问方法名后不使用括号,如下例所示

class Pizza {
    // no parentheses after crustSize
    def crustSize = 12
}

此时,调用者调用方法时不能使用括号,否则会报错

  11.png

  3. 讨论

  在调用访问方法时不适用括号并没有任何副作用,并且可以强制调用者不适用括号进行调用

  2.7 创建接受可变参数的方法

  1. 问题描述

  为了使方法更为灵活,你想要定义一个接受可变参数的方法

  2. 解决方案

  在参数字段类型后面添加*即可表示方法接受可变个参数 

def printAll(strings: String*) {
    strings.foreach(println)
}

 针对以上方法,可以有如下调用  

printAll()
printAll("foo")
printAll("foo", "bar")
printAll("foo", "bar", "baz")

 可以使用_*操作符来适应序列(Array、List、Seq、Vector等),所以其也可被用作实参调用方法  

// a sequence of strings
val fruits = List("apple", "banana", "cherry")
// pass the sequence to the varargs field
printAll(fruits: _*)

3. 讨论

  当定义一个包含可变参数的方法时,其必须要放在方法签名的最后,在可变参数后面定义一个参数是非法的

  15.png

  并且一个方法中只能有一个可变参数,当一个参数为可变参数,调用时你不需要提供任何参数,如下

  16.png

  当定义一个接受可变个整形的参数的方法时,当使用(a)参数调用(b)无参数调用,其结果不相同

  17.png

  当使用一个或多个参数调用时,其是第一个种情况,当不使用参数调用时,其是第二种情况,是空列表,这样可以防止抛出异常

  2.8 定义可抛出异常的方法

  1. 问题描述

  你想要定义一个可以抛出异常的方法,这样可以警告调用者,或者是你的代码将会被Java代码调用

  2. 解决方案

  使用@throws注释来声明可能抛出的异常,将注释放在方法之前

@throws(classOf[Exception])
override def play {
    // exception throwing code here ...
}

 当一个方法可能抛出多个异常时,将其一一列出 

@throws(classOf[IOException])
@throws(classOf[LineUnavailableException])
@throws(classOf[UnsupportedAudioFileException])
def playSoundFileWithJavaAudio {
    // exception throwing code here ...
}

3. 讨论

  Scala使用注释声明异常与Java的以下处理方式相同 

public void play() throws FooException {
    // code here ...
}

 Scala的受检查异常与Java的不相同,Scala不需要方法声明会抛出的异常,并且不需要调用者捕捉异常

  18.png

  即便Scala不需要异常时受检查的,如果不进行测试,也会出现Java中的结果,在下面的代码中,第二个println永远不会被调用 

object BoomTest extends App {
    def boom { throw new Exception }
    println("Before boom")
    boom
    // this line is never reached
    println("After boom")
}

2.9 支持流式编程风格

  1. 问题描述

  你想要创建一个调用可以使用流式风格编程的API,其也被称为方法链

  2. 解决方案

  流式编程风格可以让你的方法调用聚合在一起,如下所示 

person.setFirstName("LEE")
.setLastName("SF")
.setAge(25)
.setCity("WH")
.setState("HB")

为了支持这种风格,做法如下

    · 如果类可以被继承,可将方法的返回类型定义为this.type

    · 如果类不能被继承,可将方法的返回类型定义为this

  下面示例展示了this.type作为set*方法的返回类型  

class Person {
    protected var fname = ""
    protected var lname = ""
    def setFirstName(firstName: String): this.type = {
        fname = firstName
        this
    }
    def setLastName(lastName: String): this.type = {
        lname = lastName
        this
    }
}
class Employee extends Person {
    protected var role = ""
    def setRole(role: String): this.type = {
        this.role = role
        this
    }
    override def toString = {
        "%s, %s, %s".format(fname, lname, role)
    }
}

使用如下 

object Main extends App {
    val employee = new Employee
    // use the fluent methods
    employee.setFirstName("Al")
    .setLastName("Alexander")
    .setRole("Developer")
    println(employee)
}

3. 讨论

  如果确定类不会被继承,则将返回类型定义为this.type毫无意义,可以直接返回this即可,如下例所示

final class Pizza {
    import scala.collection.mutable.ArrayBuffer
    private val toppings = ArrayBuffer[String]()
    private var crustSize = 0
    private var crustType = ""
    def addTopping(topping: String) = {
        toppings += topping
        this
    }
    def setCrustSize(crustSize: Int) = {
        this.crustSize = crustSize
        this
    }
    def setCrustType(crustType: String) = {
        this.crustType = crustType
        this
    }
    def print() {
        println(s"crust size: $crustSize")
        println(s"crust type: $crustType")
        println(s"toppings: $toppings")
    }
}

 使用如下 

object FluentPizzaTest extends App {
    val p = new Pizza
    p.setCrustSize(14)
    .setCrustType("thin")
    .addTopping("cheese")
    .addTopping("green olives")
    .print()
}

 当类能够被继承时,则需要将返回类型定义为this.type,这使得流式风格在子类中也可以使用


三、总结



  本篇主要讲解了Scala中方法的一些使用技巧,谢谢各位园友的观看~

目录
相关文章
|
Java Scala 数据安全/隐私保护
【Scala】Scala之Methods(上)
前面学习了Scala的Class,下面接着学习Method(方法)。
110 0
【Scala】Scala之Methods(上)
|
SQL 消息中间件 分布式计算
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
917 0
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
|
3月前
|
分布式计算 资源调度 Java
Scala+Spark+Hadoop+IDEA实现WordCount单词计数,上传并执行任务(简单实例-下)
Scala+Spark+Hadoop+IDEA实现WordCount单词计数,上传并执行任务(简单实例-下)
37 0
|
3月前
|
分布式计算 Hadoop Scala
Scala +Spark+Hadoop+Zookeeper+IDEA实现WordCount单词计数(简单实例-上)
Scala +Spark+Hadoop+Zookeeper+IDEA实现WordCount单词计数(简单实例-上)
34 0
|
4月前
|
SQL 存储 分布式计算
在scala中使用spark
在scala中使用spark
227 0
|
4月前
|
分布式计算 Java Scala
spark 与 scala 的对应版本查看、在idea中maven版本不要选择17,弄了好久,换成11就可以啦
spark 与 scala 的对应版本查看、.在idea中maven版本不要选择17,弄了好久,换成11就可以啦
302 2
|
4月前
|
分布式计算 Java Scala
Spark编程语言选择:Scala、Java和Python
Spark编程语言选择:Scala、Java和Python
Spark编程语言选择:Scala、Java和Python
|
4月前
|
分布式计算 数据处理 Scala
Spark 集群和 Scala 编程语言的关系
Spark 集群和 Scala 编程语言的关系
|
存储 分布式计算 Scala
Spark-RDD 键值对的操作(Scala版)
Spark-RDD 键值对的操作(Scala版)