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

简介: 快速学习函数使用注意事项和细节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")

}

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
数据采集 机器学习/深度学习 数据可视化
【优秀python web系统毕设】基于python的全国招聘数据分析可视化系统,包括随机森林算法
本文介绍了一个基于Python的全国招聘数据分析可视化系统,该系统利用数据挖掘技术、随机森林算法和数据可视化技术,从招聘网站抓取数据,进行处理、分析和预测,帮助用户洞察招聘市场,为求职者和企业提供决策支持。
950 3
|
关系型数据库 MySQL Linux
在CentOs7虚拟机Linux离线安装mysql5.6(亲测可用)
该博客文章详细记录了在CentOS 7虚拟机上离线安装MySQL 5.6版本的完整过程,包括下载安装包、导入虚拟机、卸载MariaDB、配置文件设置、服务启动和权限配置等步骤。
在CentOs7虚拟机Linux离线安装mysql5.6(亲测可用)
|
Linux Python Windows
一个Python模块Pendulum的问题
一个Python模块Pendulum的问题
107 0
|
存储 关系型数据库 MySQL
源码包安装mariadb
**MariaDB**是MySQL的一个开源分支,由社区维护,提供高性能、安全且与MySQL高度兼容的数据库解决方案。它使用XtraDB和Maria存储引擎替代InnoDB和MyISAM。特点是开源、高性能、兼容性和安全性,广泛应用于各种场景和操作系统。在Redhat 9.2上安装MariaDB 10.6.17,首先配置yum源,检查现有MySQL/MariaDB,安装依赖包,下载源码,解压并配置编译环境,使用cmake和make编译安装,初始化数据库,创建用户,设置密码,添加启动脚本至开机自启,并执行安全初始化设置。
460 0
|
机器学习/深度学习 存储 人工智能
深度学习模型部署综述(ONNX/NCNN/OpenVINO/TensorRT)(上)
今天自动驾驶之心很荣幸邀请到逻辑牛分享深度学习部署的入门介绍,带大家盘一盘ONNX、NCNN、OpenVINO等框架的使用场景、框架特点及代码示例。
深度学习模型部署综述(ONNX/NCNN/OpenVINO/TensorRT)(上)
|
人工智能 移动开发 数据可视化
推荐几个不用写代码也能做游戏的工具
推荐几个不用写代码也能做游戏的工具
2969 0
|
缓存 开发工具
ADMob 原生广告展示不完全,mediaView无图片数据
在接入原生广告时,比如在splash 请求一个原生广告,然后缓存起来,跳转带首页展示一个原生广告,结果遇到了广告展示不完全的问题(有文案,title,appIcon,点击按钮,如果不缓存直接请求展示则没有问题),可以进行点击跳转,但是却没有广告大图,改了好一会儿,终于解决了这个问题。
二. 进制
为什么要学习进制 因为计算机只认识二进制, 也就是0和1, 为了更好地学习计算机, 我们要深入的理解学习进制
205 0
二. 进制
|
算法 Python
Python基础——bisect模块
这个模块对有序列表提供了支持,使得他们可以在插入新数据仍然保持有序。
259 0