从0开始学习scala-函数定义与使用、默认参数、传名调用、可变参数

函数定义与使用

方法定义由一个 def 关键字开始,紧接着是可选的参数列表,一个冒号 : 和方法的返回类型,一个等于号 = ,最后是方法的主体。

def functionName ([参数列表]) : [return type] = {
   function body
   return [expr]
}

以上代码中 return type 可以是任意合法的 Scala 数据类型。参数列表中的参数可以使用逗号分隔。

函数定义与调用实列

object Function {
  def main(args: Array[String]): Unit = {
    //当形参数量为0时括号可以不写
    sayHello

    sayHello("xiaoming")
    
    println(add(1, 2))

    //当函数体只有一行时{}可以不写
    def simpleAdd(x: Int, y: Int) = x + y
    println(simpleAdd(1, 2))
  }

  //无返回值函数
  def sayHello(): Unit = {
    println("say hello")
  }

  def sayHello(name: String): Unit = {
    println(s"$name hello")
  }

  //有返回值函数 以Int为列
  def add(x: Int, y: Int): Int = {
    x + y //最后一行为返回值 无需return
  }
}

默认参数

scala在函数定义时允许指定参数的默认值,当参数调用时若不传递该参数则为默认值,若传则以你传的参数为准

注意:

  1. 调用只有一个默认参数的函数时,()不可以省略
object DefaultParamFunction {
  def main(args: Array[String]): Unit = {
    //注意默认参数时,()不可以省略
    sayHello() //xiaoming say hello
    sayHello("agou") //agou say hello

  }

  def sayHello(name: String = "xiaoming"): Unit = {
    println(s"$name say hello")
  }

}

传名调用

写在前面: 本模块部分内容借鉴了狗叔的博客(Scala从零开始:函数参数的传名调用(call-by-name)和传值调用(call-by-value))

简单示例

object CallByName {
  def main(args: Array[String]): Unit = {
    param2(param1())
  }

  def param1() = {
    println("param1函数======")
    100
  }

  def param2(t: => Int) = {
    println(s"param2打印t======$t")
  }

}

传名调用与传值调用的区别

传值调用方式:就是在调用之前已经将参数表达式的值计算完毕,而传名调用是在函数内部进行参数表达式的值计算的。

object Add {
  //传名调用
  def addByName(a: Int, b: => Int) = a + b 
  //传值调用
  def addByValue(a: Int, b: Int) = a + b 
}

当纯从语法上可以看出,使用传名调用时,在参数名称和参数类型中间有一个=》符号。
以a为2,b为2 + 2为例,他们在Scala解释器进行参数规约(reduction)时的顺序分别是这样的:

  addByName(2, 2 + 2)
->2 + (2 + 2)
->2 + 4
->6

  addByValue(2, 2 + 2)
->addByValue(2, 4)
->2 + 4
->6

你可能会说结果不都是6吗??没有区别啊,那么回头看看我们之前所说的传名调用是在函数内部进行参数表达式的值计算的, 再仔细看2+(2+2)与2+4其实是有很大区别的。这种区别明显体现在循环时的重复调用,我们看下面这个列子,你就会发现传名调用是每次都会算一下,而传值调用是在调用前就算好了以后都不会再算了。

object CallByName {
  //最开始拥有的软妹币
  var money = 10
  //每天喝掉一个软妹币
  def drink: Unit = {
    money -= 1
  }
  //数钱时要算上被喝掉的软妹币
  def count: Int = {
    drink
    money
  }

  //传名调用
  def printByName(x: => Int): Unit = {
    for(i <- 0 until 5)
      println("每天算一算,酒鬼还剩" + x + "块钱!")
  }

  //传值调用
  def printByValue(x: Int): Unit = {
    for(i <- 0 until 5)
      println("只算第一天,酒鬼还剩" + x + "块钱!")
  }

  def main(args: Array[String]) = {
    printByName(count)

    printByValue(count)
  }

}

结果:

每天算一算,酒鬼还剩9块钱!
每天算一算,酒鬼还剩8块钱!
每天算一算,酒鬼还剩7块钱!
每天算一算,酒鬼还剩6块钱!
每天算一算,酒鬼还剩5块钱!
只算第一天,酒鬼还剩4块钱!
只算第一天,酒鬼还剩4块钱!
只算第一天,酒鬼还剩4块钱!
只算第一天,酒鬼还剩4块钱!
只算第一天,酒鬼还剩4块钱!

可变参数

/**
 * 以求和计算为列,计算两个数我们需要定义一个函数入参数为a、b,计算三个数的和我们需要定义a、b、c,
 * 那么这样我们就可以使用可变参数,也就是你想传多少参数就传多少个
 */
object Varargs {
  def main(args: Array[String]): Unit = {
    println(sum(1, 2, 3, 4))
  }

  def sum(numbers: Int*) = {
    var sum = 0;
    for (number <- numbers) {
      sum += number;
    }

    sum
  }
}
### Scala可变参数默认参数值的用法 #### 可变参数Scala 中,可以通过在参数前加上 `*` 来定义可变参数。这意味着可以向函数传递零个或多个相同类型的参数[^3]。当调用带有可变参数函数,这些参数会被封装成一个数组。 以下是可变参数的一个简单示例: ```scala def sum(args: Int*): Int = { var total = 0 for (arg <- args) { total += arg } total } println(sum()) // 输出: 0 println(sum(1, 2, 3)) // 输出: 6 ``` 在这个例子中,`args` 是一个可变参数,表示它可以接受任意数量的整数作为输入。如果没有任何参数传递给 `sum()` 函数,则返回值为 0--- #### 默认参数Scala 支持为函数参数指定默认值。如果没有提供对应的参数值,在调用函数使用默认值[^2]。这种特性使得函数更加灵活,因为用户可以选择性地忽略某些参数而不影响程序运行。 下面是一个带默认参数的例子: ```scala def greet(name: String = "Guest"): Unit = { println(s"Hello, $name!") } greet() // 输出: Hello, Guest! greet("Alice") // 输出: Hello, Alice! ``` 在此代码片段中,`name` 参数有一个默认值 `"Guest"`。如果不显式设置该参数,则会在控制台打印出 `"Hello, Guest!"`;否则将显示自定义字。 --- #### 结合可变参数默认参数 还可以在同一函数里同使用这两种功能——即既允许有缺省值得固定位置形参也支持不定长度的实际传入数据集。不过需要注意的是,默认参数必须位于所有非默认参数之后[^2]。 这里给出这样一个综合运用两者的实例: ```scala def log(messages: String*, level: String = "INFO"): Unit = { messages.foreach(msg => println(s"$level: $msg")) } log(level = "ERROR", messages = Array("Error occurred")) // ERROR: Error occurred log("Start processing", "End processing") // INFO: Start processing\nINFO: End processing ``` 此案例展示了如何利用消息日志记录器来处理不同严重程度的信息条目,并且演示了即使存在额外选项也可以保持接口简洁明了的设计理念。 --- ### 总结 - **可变参数** 使用星号 (`*`) 定义,能够接收不确定数目的一组同类型元素。 - **默认参数值** 提供了一种机制让开发者预先设定好一些常用配置项以便简化实际应用场景下的编码工作量。 两者结合起来可以让 API 更具弹性同也更易于维护扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值