函数使用注意事项和细节1|学习笔记

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 快速学习函数使用注意事项和细节1。

开发者学堂课程【Scala 核心编程-基础函数使用注意事项和细节1】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/609/detail/8933


函数使用注意事项和细节1

 

内容介绍

一、细节1-5

二、细节6-10

 

一、细节1-5

目前已经把基本语法和基本的运行原理讲解完毕,这节课将对函数注意事项和细节进行讲解。对于函数的注意细节一共总结了13点,下面进行函数注意事项和细节的讨论。对于现在讲的函数也可以理解为方法,因为现在还没有学习函数编程,所以函数和方法本质上没有什么区别

1、细节1

函数的形参列表可以是多个,如果函数没有形参,调用时可以不带()

2、细节2

形参列表和返回值列表的数据类型可以是值类型和引用类型。

(1)案例演示

package com . atguigu . chapter05. fundetails

object Details01 {

def main(args: Array[string]): Unit = {

//形参列表和返回值列表的数据类型可以是值类型和引用类型

val tiger = new Tiger   //构建一个 tiger=new tiger

val tiger2 = test01(10, tiger)  //传入10, tiger,这里会返回一个 tiger,注意此处返回的 tiger 与值类型中返回的tiger 是同一个,然后进行接收 tiger

println(tiger2.name)  // 此时进行输出 tiger2,因为返回的tiger与值类型中返回的 tiger 是同一个,而值类型中已经改名为 jack,所以输出应该也为 jack

println(tiger .name)   // 再输出 tiger 也为 jack,与 java 一样,就是创建了对象 tiger 然后改名字再返回,所以 tiger tiger2是同一个对象

println(tiger .hashCode() +”“+ tiger2 . hashCode())  //那么在 scala 中也是同一个对象,这里打印出hashCode 进行证明

}

def test01(n1:Int,tiger:Tiger): Tiger= {//这里为既可以传入一个 Int 值类型,也可以传入一个引用类型Tiger,返回也可以是 Tiger 类型。体现了形参列表可以是值类型也可以是引用类型,同样返回的也可以是值或者引用。因为值类型原先返回的 Int 已经讲过了,然后再进行如上引用类型的讲解。

println("n1=" + n1) //打印 n1

tiger .name = "jack'  //tiger 名字改为 jack

tiger //最后将 tiger 进行返回,这里 return 可写可不写

}}

class Tiger { //引用类型 Tiger

//一个名字属性

var name=””

}

(2)运行结果:

D: \program\jdk8\bin \java

n1=10

jack

jack

2109957412 2109957412

可以看到 hashCode 值一样,说明 scala 与 Java 机制一样,如果只是改了名字就创建了一个新的对象是不可能的,只有在 teiger 中 new 新创建一个 tiger 对象进行返回才不是同一个对象。

3、细节3

Scala 中的函数可以根据函数体最后一行代码自行推断函数返回值类型。那么在这种情况下,return 关键字可以省略

案例演示:

def getSum(n1: Int, n2: Int): Int = {

n1+n2  //return n1+n2,return 可写可不写

}

4、细节4

因为 Scala 可以自行推断,所以在省略 return 关键字的场合,返回值类型也可以省略

案例演示:

def getSum(n1: Int, n2: Int): Int = { //也可以写成(n1: Int, n2: Int) = {(:Int 是一个整体),这种写法使用较多,因为 Scala 可以自行推断

n1+n2

}

5、细节5

如果函数明确使用 return 关键字, 那么函数返回就不能使用自行推断了,就是自行推断无效,这时要明确写成:返回类型=,否则就会报错,当然如果什么都不写,即 return 返回值为()

(1)案例演示:

package com . atguigu . chapter05. fundetails

object Details01 {

def main(args: Array[string]): Unit = {

  println(getSum2(10,30)) //传入值10,30,按理说返回应该为40,但实际返回为( )

}

def getSum(n1: Int, n2: Int): Int = {

//因为这里有明确的 return这时getSum就不能省略 Int =的 Int ,即如果写return ,返回值类型就不能省略

return n1 + n2

}

/*

def getSum(n1: Int, n2: Int) = {  //这样写会出现报错,如果函数明确使用 return 关键字, 那么就是自行推断无效,这时要明确写成:返回类型=,即要写出,如上形式。

return n1 + n2

}

*/

def getSum(n1: Int, n2: Int) { //当然如果什么都不写,即表示该函数没有返回值,代表不用类型推断,即使写了 return 也无效。

return n1 + n2

}

}

(2)运行结果:

D: \program\jdk8\bin \java

()

 

二、细节6-10

6、细节6

如果函数明确声明无返回值(声明 Unit),那么函数体中即使使用 return 关键字也不会有返回值

案例演示:

println(getSum3(9,9)) //仍然返回值为()

def getSum(n1: Int, n2: Int): Unit = {  // n1+n2返回值应该为 Int,但这里为 Unit 是因为编译器认为程序没有返回值,只要接收就行。这种写法其实与上面的不写返回值等价

return n1 + n2

}

运行结果如下:

D: \program\jdk8\bin \java

()

()

7、细节7

如果明确函数无返回值或不确定返回值类型,那么返回值类型可以省略(或声明为 Any)

案例演示:

def f3(s: String)={  //有一个函数 f3,传入 s

if(s.length >= 3)   //如果长度大于3

s+ "123"      //则返回 s+ "123"

else   

3}   //否则返回3

而 s+ "123"为 String 字符型,返回3为 int 类型,显然 s 的数据类型写什么都不合适,所以这里有两种选择,第一种为省略,使用类型推导,第二种为声明为 Any,如下

def f4(s: String): Any = { //因为 Any 是所有类的父类

if(s.length >= 3)  

s+ "123"   

else   

3}  

8、细节8

Scala 语法中任何的语法结构都可以嵌套其他语法结构(灵活),即:函数中可以再声明/

定义函数,类中可以再声明类,方法中可以再声明/定义方法

(1)案例演示:

package com. atguigu. chaptero5. fundetails

object Details03 {

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

def f1(): Unit = { //在主函数中写入 f1函数,而f1函数并不是内部函数,地位与 sayOk  一样,只是在底层会写成私有类 private final 函数

println("f1")

}

println("ok~~")//此时进行运行输出并不会输出 f1字符串,因为是定义的,所以输出为 ok~~

def sayOk(): Unit = { // 这里也是一个成员,而为了区分成员的区别,会在后台写为 private final sayOk$1 (),自动加上$进行区分

println("main sayOk") //输出主函数的 sayOk,相当于 object 的方法,但这里并没有看成函数所以也无所谓

def sayOk(): Unit = { //def sayOk()中定义 def sayOk()仍然是放在 Details03中,只是名字变为了 private final sayok$2 ()

println("sayok sayok" )

}

}}

def sayOk(): Unit ={ //成员。如果再在主函数中写一个同名的 sayOk 也是不会报错的,甚至还可以在 sayOk中嵌套 sayOk,如上。

println("main sayOk" )

}

而关于f1是否是内部函数还是和 sayok()同地位的函数可以打开相应的 class 文件进行查看,案例中打开Details03$.class 文件进行查看,可以看到 f1仍然是对应类的方法,只是 f1是私有的 final 方法,不能被更改也不能被继承下去,如:

public final class Detail303$

{

public static final MODULE$;

static

new () ;

}

public void main (String[] arga)

Predef. . MODULE$ . print1n("ok--");

}

public void sayOk ()

Predef. .MODULE$.print1n("main sayOk");

}

private final void f1$1 ()

Predef. .MODULE$. println("f1");

}

(2)此时运行上述代码:

D: \program\jdk8\bin \java

ok~~

运行完成后打开编译工具进行查看,如下:

private final void sayOk$2 ()

Predef. . MODULE$ . println("sayok sayok");

private final void sayOk$1 ()

Predef. . MODULE$ . println("main sayOk");

说明并不是在主函数内部定义的函数就是内部函数,并且地位和 sayOk 一样,只是修饰符发生了一些变化而已。

9、细节9

Scala 函数的形参,在声明参数时,可以直接赋初始值(默认值),这时调用函数时,如果没有指定实参,则会使用默认值。如果指定了实参,则实参会覆盖默认值。

案例演示:

package com. atguigu. chapter05. fundetails

object Details04 {

def main(args: Array[String]): Unit = {  //函数 main,传入 args,

println(sayOk("mary")) //如果不传值的话调用的结果应该是默认值 jack,如果此时运行结果为 jack ok!而如果传入值"mary",那么就会把默认值覆盖掉,所以运行结果为 mary ok!

}

//name.形参的默认值 jack

def sayok(name : String = "jack"): string= {

return name +"ok! "

}

}

10、细节10

如果函数存在多个参数,每一个参数都可以设定默认值,那么这个时候,传递的参数到底是覆盖默认值,还是赋值给没有默认值的参数,就不确定了(默认按照声明顺序[从左到右])。在这种情况下,可以采用带名参数[案例演示+练习]

(1)案例演示:

package com . atguigu. chapter05. fundetails

object DetailParameter05 {

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

mysqlCon()

}

def mysqlCon(add: String = "localhost",port :Int = 3306, //mysqlCon 函数,里面有本地地址add,port 默认为3306

user:String = "root", pwd : String = "root"): Unit = {  //用户名密码都为 root

println("add=" + add)

println("port=" + port)

printIn("user=" + user)

println("pwd=" + pwd)

}}

此时什么都不传入,则输出值全部采用默认值,运行结果为:

D: \program\jdk8\bin \java

add=localhost

port=3306

user= root

pwd=root

那么如果修改代码为:

def main(args: Array[string]): Unit = {

mysqlcon()

mysqlCon("127.0.0.1",7777) //传入"127.0.0.1",7777,并且遵守从左到右覆盖,所以此时 add 被127.0.0.1覆盖,port 被7777覆盖

}

运行结果为:

D: \program\jdk8\bin \java

add=127.0.0.1

port=7777

user= root

pwd=root

那么如果希望指定覆盖某个默认值,则使用带名参数即可比如修改用户名和密码,修改代码为:

def main(args: Array[string]): Unit = {

//mysqlcon()

//mysqlCon("127.0.0.1",7777)

mysqlcon(user ="tom"pwd ="123" ) //如果直接写 mysqlcon("tom""123" )是不行的,因为默认是从左到右覆盖,tom 还可以与 String 进行匹配,但是123与 Int 类型是不能匹配的,所以可以写带名参数,就是写入参数名跟上等号

运行结果为:

D: \program\jdk8\bin \java

add=localhost

port=3306

user=tom

pwd=123

(2)练习

观察如下代码,分析程序输出结果:

def f6( p1 :String= "v1"p2 : String ) {

println(p1 + p2);

}

f6("v2") :分析为 p1+p2输出应该为 v2,而因为 p2没有默认值,v2应该按照从左到右覆盖,v2则把 v1覆盖掉,但是p2没有给值,所以会报错。

f6(p2="v2"):这里使用了代名参数,所以输出成功,为 v2

下面进行代码验证:

package com . atguigu. chapter05. fundetails

object DetailParameter05 {

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

//f6("v2") 这里直接出现报错,报错为没有指定 p2的值,只有指定了 p2的值才行,比如("v2"”v3”),指定 v3

f6(p2="v2")

}

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
编译器 Scala 开发者
函数使用注意事项和细节2|学习笔记
快速学习函数使用注意事项和细节2。
|
Scala 开发者
包对象注意事项和细节说明|学习笔记
快速学习包对象注意事项和细节说明。
包对象注意事项和细节说明|学习笔记
|
Go vr&ar 开发者
切片注意事项和细节(3) | 学习笔记
简介:快速学习切片注意事项和细节(3)
切片注意事项和细节(3) | 学习笔记
|
Go 开发者
切片注意事项和细节(1) | 学习笔记
简介:快速学习切片注意事项和细节(1)
133 0
切片注意事项和细节(1) | 学习笔记
|
存储 程序员 Go
切片注意事项和细节(2) | 学习笔记
简介:快速学习切片注意事项和细节(2)
147 0
切片注意事项和细节(2) | 学习笔记
|
编译器 Go 开发者
包使用注意事项和细节(1)|学习笔记
快速学习包使用注意事项和细节(1)
包使用注意事项和细节(1)|学习笔记
|
网络协议 程序员 测试技术
管道的注意事项和细节(2)|学习笔记
快速学习管道的注意事项和细节(2),使用 select 可以解决从管道取数据的阻塞问题【案例演示】 我们在管道读取数据的时候要 close 管道,如果没有关闭,这个时候他会阻塞,而且会发生死锁,但有些情况如想在不想关闭的情况下也不被阻塞的话,我们就要使用 select
管道的注意事项和细节(2)|学习笔记
|
Java 编译器 Scala
函数使用注意事项和细节3|学习笔记
快速学习函数使用注意事项和细节3。
|
Go 开发者
函数注意事项和细节(1) | 学习笔记
简介:快速学习函数注意事项和细节(1)
|
Go 开发者
函数注意事项和细节(2) | 学习笔记
简介:快速学习函数注意事项和细节(2)