Kotlin基础教程之Run,标签Label,函数Function-Type

Kotlin基础教程之Run,标签Label,函数Function-Type

在Java中可以使用{}建立一个匿名的代码块,代码块会被正常的执行,除了改变了作用域之外,似乎并没有什么其他的作用。然而在Kotlin中却不能这么做,这是为什么呢?

其实,我们都知道一个函数一定与一个内存地址相关,而一个匿名的代码块其实也相当于是一个匿名的函数。在Kotlin中一般使用run函数来运行一段匿名代码块。

如下:

在Kotlin中使用标识符后跟@符号来定义一个标签,使用@后跟标识符来引用一个标签,run函数的语法初看起来似有一些怪异,其实run函数以一个函数作为参数,而一个匿名的代码块就可以是一个匿名函数,当我们在IntelliJ IDEA中把鼠标光标放到匿名代码块的大括号上时,会显示出匿名代码块对应的函数签名

local final fun <anonymous> ():Int defined in com.kotlin_learn.control_flow.fun_run

如图:

local代表作用域,定义在函数内部,作用域仅为local,final代表不可变,<anonymous>即为匿名,()是参数列表,Int是返回值,com.kotlin_learn.control_flow.fun_run是函数定义位置的完整路径。

由此可见,run函数的参数,那段匿名代码块被编译器转换为了一个匿名函数是毫无疑问的。

当然run函数是可以有返回值的,所以匿名代码块也可以是有返回值的匿名函数。

每一个函数都与一个或多个地址相对应,而每一个标签Label也是与一个或多个地址相对应,所以函数本身即是标签。

所以可以使用return@run之类的语法。

匿名函数虽然没有函数名,然而我们可以定义一个具名标签来代表这个函数,于是可以使用return@outer 2将2返回给i。

也许有人会有疑问,为什么不直接使用return 2呢,原因是return 将会从fun_run函数返回,而不是从匿名函数返回。

关于return和函数嵌套定义的问题下面还会说。

这段代码的运行结果如下:

接下来说一说forEach函数,与其他语言中不同,在Kotlin中forEach并不是一种语法,而是一类函数,forEach是iterator的函数,任何实现了iterator的类都可以使用forEach。forEach函数的参数也是一个函数,其参数是一个模板函数,可以是具名函数,匿名函数,lambda。forEach会对iterator迭代的每一个元素都调用一次传入的函数。

之所以讲到forEach,是为了熟悉标签的用法和return的用法。

如下:

别忘了infix function call。

运行结果如下:

接下来说一说function type,讨论一下函数。

对程序员来说,函数是很熟悉的,然而我们对函数就真的那么熟悉么?

函数也可以是类型,可以是变量,甚至常量。

如下:

在这段代码中我们定义了几个函数类型的变量和常量,并且在之间进行赋值等操作,其实和C++中的函数指针很相似,但是也有独特的地方。比如嵌套函数定义,函数标签的引用以及带标签的返回值等等。我们也看到了在一个匿名函数(end1代表的那个)中如何使用lambda表达式定义函数的参数列表和自动判断的返回类型。

这段代码运行结果如下:

刚才我们提到了函数嵌套定义,这是一个需要小心的地方。

看如下的代码:

从Java/C++一系出身的程序员(比如我:))很容易把这里的嵌套函数定义看成是匿名代码块的嵌套,以为程序会从外往内执行。从Pascal/PL一系出身的程序员就不会有这种问题,千万记住,函数虽然可以嵌套定义,但是如果没有调用是不会从外向内执行的。

所以输出很简单:

我们也看到了return的用法,这里的f1,f2,f3虽然是内部定义的函数,但是依然可以作为标签使用。

可见Kotlin是一种集大成的语言,甚至借鉴了古老的unix脚本和Pascal的语法,借鉴了很多语言的特性,再加上强大的编译器(Kotlin编译器会帮你做很多东西,远比其他语言做的多得多),使Kotlin的代码非常简洁优雅而且编程相当灵活高效。

在Kotlin中,太多的功能都是通过使用函数作为参数来实现,有的已经不能叫做语法,然而函数嵌套,infix function call,lambda,函数参数,可变参数列表,灵活的标签,强大的return,自动类型判断,Range,iterator,操作符重载,省略,模板...这些太多的功能,导致Kotlin的语法眼花缭乱,虽然有时看起来很优雅,但是也可能给人阅读代码带来巨大的困难。

最后以一段没什么卵用的代码结束本篇。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Kotlin基础教程之函数定义与变量声明

    Kotlin基础教程之函数定义与变量声明 可以看到,函数定义就是 <访问控制符> <函数名> <参数列表> <:返回类型(不写就是无返回类型)> { 函数体 } 单语句函数可以简写,比如add函数和add1函数效果是一样的 变量定义 var <标识符> : <类型> = <初始化值> 常量定义 val <标识符> : <类型> = <初始化值> 常量与变量都可以没有初始化值,但是在引用前

  • Kotlin基础教程之数据类型

    Kotlin基础教程之数据类型 一切都是对象. 在Kotlin中一切都是对象.Kotlin有一些基本类型Boolean,Byte,Shot,Int,Long,Float,Double 在Kotlin中没有原始类型,以上这些类型都是对象,比如 运行结果如下 Kotlin支持16进制字面值,二进制字面值和科学记数法,官方文档中没有提到8进制 所有基本的几个数据类型不会进行显式类型转换,这一点尤为重要!那么如何进行转换呢?如下: 可以使用toLong,toInt,toShort,toChar等函数进行

  • Kotlin基础教程之面向对象

    Kotlin 面向对象 这几天一直在准备考试,实在没有时间,已经过去了这么久,终于要到面向对象了! 先看看Kotlin中的类长什么样吧. 可以看到Kotlin中的类还是很普通的,大多与Java相似,比较特殊的有: 每一个构造函数都必须为每一个成员变量赋予初值. primary constructor,这个构造函数的头部紧跟在类名之后,函数体却在类中,是由init关键字包含的一个代码块,这种函数头和函数体分开的写法还是很少有的,其实这两个部分会被整合成一个构造函数,使用jd-gui反编译class

  • Kotlin基础教程之操作符与操作符重载

    Kotlin基础教程之操作符与操作符重载 Kotlin操作符的使用方法与其他语言差不多,最大的特点就在于infix function call(事实上infix function call并不是操作符的特性,而是函数的特性)和操作符重载. 可以看到在Kotlin中大部分的操作符都与一个函数相对应,之所以这样做,大概是为了进行操作符重载. Kotlin官方文档中强调"=赋值"操作在Kotlin中不是操作符,换句话说类似于x = y = z这样的连续赋值并不被允许(甚至赋值操作也不能和常规

  • kotlin基础教程之类和继承

    kotlin基础教程之类和继承 类声明 使用class关键字声明类,查看其声明格式: : modifiers ("class" | "interface") SimpleName typeParameters? primaryConstructor? (":" annotations delegationSpecifier{","})? typeConstraints (classBody? | enumClassBody)

  • Kotlin基础教程之控制流(顺序,分支,循环)

    Kotlin的控制流与其他语言一样,顺序,分支,循环 顺序语句就不多说,分支有两种,if-else和when(类似于Java中的switch) if语句: 运行结果: Java中的case语句不仅支持整数值,最新的JVM还支持字符串,Kotlin的when语句更是强大,开关变量甚至可以是Double,Array等各种类型,换句话说when语句比switch语句强大,与if-else语句的能力已经不相上下: 运行结果: while和do-while语句 与Java没有太大区别 运行结果: for循

  • Kotlin教程之基本数据类型

    Kotlin教程之基本数据类型的学习 基本类型 我们知道java的基本类型分为基本数据类型: int 普通整型 float 浮点型 char 字符型 short 短整型 byte 字节型 long 长整型 double 双精度 boolean 布尔型 和引用数据类型: class Type 类类型 interface Type 接口类型 array Type 数组类型 null Type 空类型 在 Kotlin 中,所有变量的成员方法和属性都是一个对象.一些类型是内建的,因为它们的实现是优化过

  • Kotlin教程之函数和包的定义和流程控制

    Kotlin教程之函数和包的定义和流程控制 包名的定义 在xxx.kt文件的顶部进行定义,使用package关键字,定义后,引用包内函数或类,使用包前缀: package cn.jasonmarzw //包定义 fun doSomething(){} // 定义的函数 class User(){} //定义的类 在其他文件中使用时: 可以直接使用 cn.jasonmarzw.doSomething()和 cn.jasonmarzw.User进行调用.可以像Java一样,使用import引入所需要

  • Kotlin基础教程之Run,标签Label,函数Function-Type

    Kotlin基础教程之Run,标签Label,函数Function-Type 在Java中可以使用{}建立一个匿名的代码块,代码块会被正常的执行,除了改变了作用域之外,似乎并没有什么其他的作用.然而在Kotlin中却不能这么做,这是为什么呢? 其实,我们都知道一个函数一定与一个内存地址相关,而一个匿名的代码块其实也相当于是一个匿名的函数.在Kotlin中一般使用run函数来运行一段匿名代码块. 如下: 在Kotlin中使用标识符后跟@符号来定义一个标签,使用@后跟标识符来引用一个标签,run函数

  • Kotlin基础教程之dataclass,objectclass,use函数,类扩展,socket

    Kotlin基础教程之dataclass,objectclass,use函数,类扩展,socket Kotlin提供了一些机制来扩展已有的类,如下: 还记得我们之前写过的Point3D类吗?(将其略作修改,将成员变量改为Double类型) 让我们为其扩展一个length函数 扩展的方法很简单,只要在函数名前面加上类名就行了. 这样Point3D的对象就有了一个名为length的方法. 运行的结果不出所料: 除此之外,在Kotlin中还有一些特殊的类,比如Data Class: 有些类只包含数据,

  • Kotlin中let()with()run()apply()also()函数的使用方法与区别

    相比Java, Kotlin提供了不少高级语法特性.对于一个Kotlin的初学者来说经常会写出一些不够优雅的代码.在Kotlin中的源码标准库(Standard.kt)中提供了一些Kotlin扩展的内置函数可以优化kotlin的编码.Standard.kt是Kotlin库的一部分,它定义了一些基本函数. 这个源代码文件虽然一共不到50行代码,但是这些函数功能都非常强大. 一.回调函数的Kotin的lambda的简化 在Kotlin中对Java中的一些的接口的回调做了一些优化,可以使用一个lamb

  • jQuery EasyUI基础教程之EasyUI常用组件(推荐)

    本文主要内容是介绍EasyUI的一些常用组件的使用,都是一些非常基础的知识,适合入门者学习,主要包括Base(基础).Layout(布局).菜单和按钮.表单.窗口.表格和树等的使用.要求完全掌握这些内容,学会查阅文档,了解开发基本思想.如果想进一步深入学习,可以直接去官网进行学习,查阅文档等http://www.jeasyui.com/. 一.简介 EasyUI是一种第三方组织开发的,开源的,功能强大的,基于jquery的插件库. 主要可以用于web的后台前端.jQuery EasyUI 提供易

  • Jquery基础教程之DOM操作

    对于dom的全称大家都知道吧,DOM是Document Object Model的缩写,其意思是文档对象模型.DOM是一种与浏览器.平台.语言无关的接口,使用dom接口很容易的访问页面中所有标准组件.dom操作一般可以分为三个方面即DOM Core(核心).HTM-Dom和CSS-DOM. 每一个网页都可以用DOM表示出来,每个DOM都可以看作是一棵DOM树.下面的html页面结构可以构建出一棵DOM树,代码: 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DT

  • JavaWeb基础教程之Java基础加强版

    1.myeclipse的安装和使用 * eclipse:是一个免费的开发工具 * myeclipse:是一个收费的插件,破解myeclipse, ** 安装目录的要求: 不能有中文和空格 ** 安装完成之后,选择一个工作空间 ,这个工作空间不能有中文和空格 * 破解myeclipse ** 运行run.bat文件,但是运行之前,必须要安装jdk,通过配置环境变量 * myeclipse的使用 * 创建一个工程 - 类型 java project web project - 选择依赖的jdk,可以

  • Python基础教程之if判断,while循环,循环嵌套

    if判断 判断的定义 如果条件满足,就做一件事:条件不满足,就做另一件事:  判断语句又被称为分支语句,有判断,才有分支: if判断语句基本语法 if语句格式: if 判断的条件:     条件成立后做的事     ... ... 代码缩进为一个tab键,或者四个空格,官方建议使用空格:但应注意,在python开发中,tab和空格不能混用! 判断年龄示例: # 判断是否成年,成年则可以进网吧 age = 19 if age>=18: print("你满了18岁,可以进网吧") i

  • 微信小程序基础教程之echart的使用

    前言 先看下最终实现的效果–自己做的小demo 首先到ECharts官网下载官网地址 根据上面的网址下载代码把ec-canvas文件拷贝下来放到你自己的项目中, 我放的是tool文件夹下面,你们随意引入的时候注意路径就行 2.使用 然后在你需要用的页面引入,在json中加入,这里要注意路径echart.json "usingComponents": { "tab":"../../component/tabs/tab", "ec-canv

  • MySQL基础教程之DML语句详解

    目录 DML 语句 1.插入记录 2.更新记录 3.简单查询记录 4.删除记录 5.查询记录详解(DQL语句) 5.1.查询不重复的记录 5.2.条件查询 5.3.聚合查询 5.4.排序查询 5.5.limit查询 5.6.连表查询 5.7.子查询 5.8.记录联合 5.9.select语句的执行顺序 6.总结 DML 语句 DML(Data Manipulation Language)语句:数据操纵语句. 用途:用于添加.修改.删除和查询数据库记录,并检查数据完整性. 常用关键字:insert

  • Python基础教程之pytest参数化详解

    目录 前言 源代码分析 装饰测试类 装饰测试函数 单个数据 一组数据 组合数据 标记用例 嵌套字典 增加测试结果可读性 总结 前言 上篇博文介绍过,pytest是目前比较成熟功能齐全的测试框架,使用率肯定也不断攀升.在实际 工作中,许多测试用例都是类似的重复,一个个写最后代码会显得很冗余.这里,我们来了解一下 @pytest.mark.parametrize装饰器,可以很好的解决上述问题. 源代码分析 def parametrize(self,argnames, argvalues, indir

随机推荐