作者:Antonio Leiva

时间:Feb 8, 2017

原文链接:https://antonioleiva.com/generic-functions-kotlin/

Kotlin的一些特性组合起来与泛型混合使用创建函数可以极大的简化你的编码,且保证它的可读性。

在Kotlin库中,有几个函数非常实用,一旦你掌握它们的概念使用起来就非常容易。

with函数

尽管Kotlin标准库中有几个相似的函数,但是,我计划聚焦在with的各个部分上。

这个函数允许做什么?用了它,我们可以用一变量的代码块作为其上下文,这样就不需要每次使用它重复它的名字。

它们可以替代构建器,不需要为每个类创建特定构建器。

例如,回到前面文章的ViewGroup例子,可以转换这行代码:

 val childViews = (0..viewGroup.childCount - 1).map { viewGroup.getChildAt(it) }

到:

 with(viewGroup) {
val childViews = (0..childCount - 1).map { getChildAt(it) }
}

如你所见,括号内代码的行为就像是其在本类中。

那我们如何得到这样呢?我们在之前的扩展函数中已经见过了。

扩展函数作为其他函数的自变量

这事情越来越复杂了,但是这是非常有用的,你需要理解它。

你能够定义扩展函数为另一个函数的参数。

你怎样实现with函数执行前面的例子?最简单就是这样:

 inline fun with(view: ViewGroup, f: ViewGroup.() -> Unit) {
view.f()
}

上面代码以参数形式接收ViewGroup,且一个用于ViewGroup的扩展函数。ViewGroup可无障碍执行那个函数。

但是,这限制较多。对数据的每种类型我们需要一个类似的函数?

当然不是。

泛型类型

我们能够十分容易地用泛型转换上面的函数。只需用T替换ViewGroup:

 inline fun with(obj: T, f: T.() -> Unit) {
obj.f()
}

现在它就可以用于任何类型。例如:

 with(textView) {
text = "Hello World"
visibility = View.VISIBLE
textSize = sp(14).toFloat()
}

但是,在我们开始讨论时,我们忽略一项重要的能力:构建器的角色。

泛型类型的返回值

如果我们想要一个真正的构建器,我们就需要以某种方式返回构建值:

 inline fun with(obj: T, f: T.() -> Unit): T {
obj.f()
return obj
}

那样,我们的代码应该是这样:

 val textView = with(TextView(this)) {
text = "Hello World"
visibility = View.VISIBLE
textSize = sp(14).toFloat()
}

注:sp() 是Anko库的函数,在这系列文章前面谈论过它。

如果你看函数的正式定义,它非常类似我们已经做的:

 public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()

这里主要的区别在于扩展函数返回的值可能会不同传递参数。

为了获得与使用常规函数的相同结果,我们需要这样做:

 val textView = with(TextView(this)) {
text = "Hello World"
visibility = View.VISIBLE
textSize = sp(14).toFloat()
this
}

最后一行意思是将返回执行扩展函数的对象。

其他有趣的函数

有一个函数功能非常类似我们在前一节得到的,它叫apply。

apply

这个函数作为对象的扩展函数,而不是对象的参数:

 val textView = TextView(this).apply {
text = "Hello World"
visibility = View.VISIBLE
textSize = sp(14).toFloat()
}

let

如果相应的对象不是null,它将只需内部函数的代码:

 textView?.text?.let { toast(it) }

仅当TextView和text都不为null,text将被显示在消息框(toast)中。

结论

结合扩展函数,利用泛型类型的能力,我们能做一些非常有趣的事情。

我鼓励你创建自己的函数以简化你的日常工作。

Kotlin中的“忍者”函数 —— 理解泛型的能力(KAD 12)的更多相关文章

  1. Lambda表达式在Kotlin中怎样工作的:setOnClickListener的转换(KAD 18)

    作者:Antonio Leiva 时间:Mar 28, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin-android/ 虽然,我在其它文章讲过一点 ...

  2. 浅谈Kotlin中的函数

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/UV23Uw_969oVhiOdo4ZKAw作者:连凌能 Kotlin,已经被Android官方 ...

  3. 深入理解javascript中的立即执行函数(function(){…})()

    投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...

  4. IIFE-js中(function(){…})()立即执行函数写法理解

    介绍IIFE IIFE的性能 使用IIFE的好处 IIFE最佳实践 jQuery优化 在Bootstrap源码(具体请看<Bootstrap源码解析>)和其他jQuery插件经常看到如下的 ...

  5. 理解Vue中的Render渲染函数

    理解Vue中的Render渲染函数 VUE一般使用template来创建HTML,然后在有的时候,我们需要使用javascript来创建html,这时候我们需要使用render函数.比如如下我想要实现 ...

  6. 数组中的reduce 函数理解

    第一次见到reduce 是在js 的高级程序设计中,它的意思是把一个数组减少为一个数,举的例子是数组中元素的求和.它接受一个函数作为参数,函数又有两个参数,一个是prev, 前一个值,一个是next, ...

  7. 理解Underscore中的_.bind函数

    最近一直忙于实习以及毕业设计的事情,所以上周阅读源码之后本周就一直没有进展.今天在写完开题报告之后又抽空看了一眼Underscore源码,发现上次没有看明白的一个函数忽然就豁然开朗了,于是赶紧写下了这 ...

  8. 在Kotlin中 使用js 函数

    在Kotlin中 使用js 函数 import javax.script.Invocable import javax.script.ScriptEngineManager fun main(args ...

  9. 深入理解javascript中的立即执行函数

    这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包住业务代码,使用jquery时比较常见,需要的朋友可以 ...

随机推荐

  1. vuejs给组件绑定原生事件

    给组件绑定事件,该事件是自定义的事件 <div id='root'> <child @click='handleClick'></child> </div&g ...

  2. LayoutParams布局

    AbsoluteLayout.LayoutParams可以重新设置坐标,然后调用setLayoutParamsLinearLayout.LayoutParams可以调用setMargins();来移动 ...

  3. 三、Object-C内存管理

    一.管理范围:任何继承了NSObject的对象,对基本数据类型无效 原理: 1.每个对象都有个引用计数器,是一个与之关联的整数 2.使用了 3.给对象发送一条retain消息,可以使对计数器+1 4. ...

  4. 深入理解 SVG 系列(一) —— SVG 基础

    来源:https://segmentfault.com/a/1190000015652209 本系列文章分为三个部分: 第一部分是 SVG 基础. 主要讲 SVG 的一些基础知识,包括 SVG 基本元 ...

  5. Wuss Weapp 一款高质量,组件齐全,高自定义的微信小程序 UI 组件库

    Wuss Weapp 一款高质量,组件齐全,高自定义的微信小程序 UI 组件库 文档 https://phonycode.github.io/wuss-weapp 扫码体验 使用微信扫一扫体验小程序组 ...

  6. Delphi7程序调用C#写的DLL解决办法(转)

    近来,因工作需要,必须解决Delphi7写的主程序调用C#写的dll的问题.在网上一番搜索,又经过种种试验,最终证明有以下两种方法可行:    编写C#dll的方法都一样,首先在vs2005中创建一个 ...

  7. 全文检索(Lucene&Solr)

    全文检索(Lucene&Solr) 1)什么是全文检索?为什么需要全文检索? 结构化数据(mysql等)方便查询,而非结构化数据(如多篇文章)是难以查询到自己需要的,所以要使用全文检索. 全文 ...

  8. webpack最小化lodash

    lodash作为一个比较常用的前端开发工具集,在使用webpack进行vendor分离的实践中,会遇到将整个lodash文件分离到vendor.js的问题.这样会使vendor.js文件变得特别大. ...

  9. JavaScript对象回收机制

    js维护了一张对象引用表: 当一个对象被创建以后,栈内就有一个a,a这个对象就指向了对这个地址,当a=new Person()执行后,引用次数加1.当a=null置空,引用次数减1.由系统来维护对象引 ...

  10. 关于json输出为null?

    原因: 该字符中含了ASCII码ETB控制符,即\x17导致json解析失败   解决方案: $params = preg_replace('/[\x00-\x1F]/', '', $params); ...