上一篇文章介绍了Kotlin新增的空安全机制,控制语句部分可算是讲完了,接下来将连续描述Kotlin如何定义和调用函数,本篇文章先介绍函数的基本用法。

前面几篇文章介绍控制语句之时,在setOnClickListener里面写了大段的代码,这不但导致onCreate方法变得很臃肿,而且代码的可读性也变差了。对于这种情况,通常的解决办法是把某段代码挪到一个独立的函数中,然后在原位置调用该函数,这样做的好处很多,不仅增强了代码的可读性,还能多次重复调用函数。那么Kotlin对函数的使用跟Java相比,有哪些区别呢?先从最常见的onCreate方法入手,Java编写的onCreate函数代码如下:

    @Override
public void onCreate(Bundle savedInstanceState) {
...
}

使用Kotlin编写的onCreate函数代码如下:

    override fun onCreate(savedInstanceState: Bundle?) {
...
}

两相对比,可以看到二者主要有以下几点区别:
1、Java使用“@Override”表示该函数是重载了父类的方法,而Kotlin使用小写的“override”在同一行表达重载操作;
2、Java使用“public”表示该函数是公共方法,而Kotlin默认函数就是公开的,所以省略了关键字“public”;
3、Java使用“void”表示该函数没有返回参数,而Kotlin不存在关键字“void”,若无返回参数则不用特别说明;
4、Kotlin新增了关键字“fun”,表示这里是函数定义,其格式类似于Java的关键字“class”,而Java不存在关键字“fun”;
5、Java声明输入参数的格式为“对象类型 对象名称”,而Kotlin声明入参的格式为“对象名称: 对象类型”;
6、Kotlin引入了空安全机制,如果某个对象允许为空的话,需要在对象类型后面加个问号“?”;
其中第五点区别的说明参见《Kotlin入门(3)基本变量类型的用法》,第六点区别的说明参见《Kotlin入门(8)空值的判断与处理》。

用惯了Java或C++,遇到Kotlin这种函数写法,一开始可能有点不适应,主要还是惯性思维在捣鬼。现在还是从最简单的函数声明开始,循序渐进逐步适应,下面是个没有输入参数也没有输出参数的函数定义:

    //没有输入参数,也没有输出参数
fun getDinnerEmpty() {
tv_process.text = "只有空盘子哟"
tv_result.text = ""
}

这个既无入参也无出参的函数,看起来就比较容易理解。下面再来一个增加了输入参数的函数定义:

    //只有输入参数
fun getDinnerInput(egg:Int, leek:Double, water:String, shell:Float) {
tv_process.text = "食材包括:两个鸡蛋、一把韭菜、一锅开水"
tv_result.text = ""
}

只要学习了前面基本变量类型的用法,这个存在入参的函数也易于接受。在上面代码的基础上,允许第三个入参为空,则相应的代码改写如下:

    //输入参数存在空值
fun getDinnerCanNull(egg:Int, leek:Double, water:String?, shell:Float) {
tv_process.text = if (water!=null) "食材包括:两个鸡蛋、一把韭菜、一锅开水" else "没有水没法做汤啦"
tv_result.text = ""
}

在变量类型后面加上问号,表示该参数可以为空,正好上一篇文章介绍了空值的判断与处理。
现在有了定义好的函数,若要在Kotlin代码中调用它们,那可一点都没变化,原来在Java中怎么调用,在Kotlin中一样采取“函数名称(参数列表)”的形式进行调用。调用代码举例如下:

    btn_input_empty.setOnClickListener { getDinnerEmpty() }
btn_input_param.setOnClickListener { getDinnerInput(2, 1111.1111, "水沝淼", 10000f) }
btn_input_null.setOnClickListener { getDinnerCanNull(2, 1111.1111, null, 10000f) }

  

上面讨论了存在输入参数的情况,如果函数需要返回输出参数,又该如何是好?在Java代码中,函数的返回参数类型在函数名称前面指定,形如“public int main(...)”,但在Kotlin中,返回参数类型却在右括号后面指定,形如“fun main(...):Int”。对于习惯了Java的开发者而言,Kotlin的这种写法着实别扭,为了方便记忆,我们姑且把函数当作一种特殊的变量,定义函数跟定义变量是同一种写法。比如Kotlin定义一个整型变量,声明代码如下所示:

    var i:Int

再看看Kotlin定义一个函数的声明代码:

    fun main():Int

如此一来,功能定义var对fun,参数类型Int对Int,唯一的区别便是函数定义多了一对括号,以及括号内部的输入参数。也许这只是巧合,但是偶然中有必然,Kotlin设计师的初衷正是把函数做为一个特殊的对象,关于这点后面的文章还会再次提到。

既然函数被当作一种特殊的变量,可是每个变量都有变量类型,如果函数存在返回参数,那自然把返回参数的类型作为函数的变量类型;可要是函数不存在返回参数,也就是Java中的void声明,那该怎么办?这里得澄清一下,Java使用void表示不存在返回参数,然而Kotlin的返回参数是一定存在着的,即使开发者不声明任何返回参数,Kotlin函数也会默认返回一个Unit类型的对象。比如前面的函数定义getDinnerEmpty(),表面上看没有返回参数,其实它的真正写法是下面的代码:

    //Unit类型表示没有返回参数,可直接省略Unit声明
fun getDinnerUnit():Unit {
tv_process.text = "只有空盘子哟"
tv_result.text = ""
}

因为Unit类型的参数无需开发者返回具体的值,所以Kotlin代码往往把函数名称后面的“:Unit”直接省略掉了;增加Unit类型的目的,就是让函数定义完全符合变量定义的形式。如果函数需要具体的输出参数,则一样要在函数末尾使用关键字“return”来返回参数值,下面代码演示了如何在函数中返回一个字符串对象:

    //只有输出参数
fun getDinnerOutput():String {
tv_process.text = "只有空盘子哟"
var dinner:String = "巧妇难为无米之炊,汝速去买菜"
return dinner
}

有了以上的各种铺垫,现在定义一个包含入参和出参的函数,写起代码便顺理成章了。如下所示的代码通过判断各种输入食材,从而输出一道色香味俱全的菜肴:

    //同时具备输入参数和输出参数
fun getDinnerFull(egg:Int, leek:Double, water:String?, shell:Float):String {
tv_process.text = if (water!=null) "食材包括:两个鸡蛋、一把韭菜、一锅开水" else "没有水没法做汤啦"
var dinner:String = "两只黄鹂鸣翠柳,\n一行白鹭上青天。\n窗含西岭千秋雪,\n门泊东吴万里船。"
return dinner
}

存在具体返回参数的函数,调用方式并无二致,以下直接给出示例代码好了:

    btn_output_empty.setOnClickListener { getDinnerUnit() }
btn_output_param.setOnClickListener { tv_result.text=getDinnerOutput() }
btn_full_param.setOnClickListener { tv_result.text=getDinnerFull(2, 1111.1111, "水沝淼", 10000f) }

  

下面是调用各种函数定义的效果动图:

__________________________________________________________________________
本文现已同步发布到微信公众号“老欧说安卓”,打开微信扫一扫下面的二维码,或者直接搜索公众号“老欧说安卓”添加关注,更快更方便地阅读技术干货。

Kotlin入门(9)函数的基本用法的更多相关文章

  1. Kotlin入门(3)基本变量类型的用法

    上一篇文章介绍了Kotlin在App开发中的简单用法,包括操纵控件对象.设置控件监听器,以及弹出Toast提示等等.也许大家已经迫不及待想要了解更深入的App开发,可是由于Kotlin是一门全新的语言 ...

  2. Kotlin入门教程——目录索引

    Kotlin是谷歌官方认可的Android开发语言,Android Studio从3.0版本开始就内置了Kotlin,所以未来在App开发中Kotlin取代Java是大势所趋,就像当初Android ...

  3. Kotlin入门(13)类成员的众生相

    上一篇文章介绍了类的简单定义及其构造方式,当时为了方便观察演示结果,在示例代码的构造函数中直接调用toast提示方法,但实际开发是不能这么干的.合理的做法是外部访问类的成员属性或者成员方法,从而获得处 ...

  4. Kotlin入门(5)字符串及其格式化

    上一篇文章介绍了数组的声明和操作,包括字符串数组的用法.注意到Kotlin的字符串类也叫String,那么String在Java和Kotlin中的用法有哪些差异呢?这便是本文所要阐述的内容了. 首先要 ...

  5. 写给Android开发者的Kotlin入门

    写给Android开发者的Kotlin入门 转 https://www.jianshu.com/p/bb53cba6c8f4 Google在今年的IO大会上宣布,将Android开发的官方语言更换为K ...

  6. Kotlin入门(11)江湖绝技之特殊函数

    上一篇文章介绍了Kotlin对函数的输入参数所做的增强之处,其实函数这块Kotlin还有好些重大改进,集中体现在几类特殊函数,比如泛型函数.内联函数.扩展函数.尾递归函数.高阶函数等等,因此本篇文章就 ...

  7. Kotlin入门(14)继承的那些事儿

    上一篇文章介绍了类对成员的声明方式与使用过程,从而初步了解了类的成员及其运用.不过早在<Kotlin入门(12)类的概貌与构造>中,提到MainActivity继承自AppCompatAc ...

  8. Kotlin——基础的函数/方法详解

    对于Kotlin中的函数来说,和JavaScript或者Lua这些语言很像,它有着这些语言的特性.但是也与这些语言就着许多不同之处.或许你更了解Java语言,然而对于Java语言来说,它不是不是闭包这 ...

  9. Kotlin入门(32)网络接口访问

    手机上的资源毕竟有限,为了获取更丰富的信息,就得到辽阔的互联网大海上冲浪.对于App自身,也要经常与服务器交互,以便获取最新的数据显示到界面上.这个客户端与服务端之间的信息交互,基本使用HTTP协议进 ...

随机推荐

  1. Dispatch Queue 内存结构

    Dispatch 源代码版本是libdispatch-84.5.5  会根据这个结构来分析dispatch_queue 对应的代码实现 参考 GCD源码分析3 -- dispatch_queue篇 ...

  2. ubuntu 16.04 下更换boost版本

    如果是新机器,没装过boost,那么直接一条命令 sudo apt-get install libboost-all-dev 头文件一般安装在 /usr/include 下面有一个目录boost,里面 ...

  3. win10 插入16k采样的耳机无法播放和录音的问题定位

    平时做智能耳机,需要经常在windows上测试不同采样率的声音信号.可是,最近在16k双声道输入的情况下, 无论系统都使用该耳机进行播放,该问题思索了好久,一直没有解决办法. 今天无意中使用了wind ...

  4. oracle中常用的对用户的操作

    创建用户:create user usr1 identified by pwd default tablespace ts1 temporary tablespace tmp; 删除用户:drop u ...

  5. 源码编译安装lnmp环境

    一.源码编译安装步骤 首先说明源码安装的好处   速度快,可自定义路径 主要有三步:1.配置 进入源码安装包  ./configure --prefix=/uer/local/nginx  可指定参数 ...

  6. 转载:https原理:证书传递、验证和数据加密、解密过程解析

    写的太好了,就是我一直想找的内容,看了这个对https立马明白多了 http://www.cnblogs.com/zhuqil/archive/2012/07/23/2604572.html 我们都知 ...

  7. myslide 插件开发知识点总结和 css3 动画性能问题的研究

    myslide 插件开发知识点总结和 css3 动画性能问题的研究 这篇文章主要是总结最近开发过程中遇到的问题.有几个问题又是不容易发现原因的问题,但是最后的结果又是很简单的. 1.手机端的 slid ...

  8. JAVA中的糕富帅技术——反射(一)

    前言 突然发现好久没写博客了,前面写的都是关于Android的东西,今天心血来潮突然有一种冲动想写一篇基于JAVA技术的博客,别问我为什么?有钱.任性! 今天就来谈谈反射机制:学过JAVA的人不一定懂 ...

  9. c time类型详解

    linux下存储时间常见的有两种存储方式,一个是从1970年01月01日 0:00:00到现在经过了多少秒,一个是用一个结构来分别存储年月日时分秒的.time_t 这种类型就是用来存储从1970年到现 ...

  10. Django models 常用数据类型

    CharField class CharField(max_length=None[, **options]) # 字符串(存储从小到大各种长度) # 如果是巨大的文本类型,可以用 TextField ...