释放Android的函数式能量(I):Kotlin语言的Lambda表达式

原文标题:Unleash functional power on Android (I): Kotlin lambdas

原文链接:http://antonioleiva.com/operator-overloading-kotlin/

原文作者:Antonio Leiva(http://antonioleiva.com/about/

原文发布:2015-08-05

虽然Java 8中已包含一些函数式工具,且如你想象那样Android开发者还不能够立即(或许甚至根本不能)使用这些工具,但是如果恰当地使用,函数式编程依然是十分强的工具。为此许多其他编程语言正开始进行解决这个问题。

现代编程语言的函数式编程

 

由于函数式编程依赖于函数和永恒性,所以函数调用总是返回相同的结果。通常,完美是在各方合理的平衡点上,所以大多数现代编程语言,如Kotlin或Scala,都在单一编程语言中,融合过程式编程和函数式编程方法,并在这两方面拥有最为先进的理念。有些问题用函数式编程来解决更合适,而有些沿用过程式编程更直接。

在Android中用Kotlin语言实现Lamba表达式

Lambda表达式是定义匿名函数的简单方法。由于Lambda表达式避免在抽象类或接口中编写明确的函数声明,进而也避免了类的实现部分,所以它是非常有用的。在Kotlin语言中,可以将一函数作为另一函数的参数。例如,可以将需要回调(callback)的函数简单化为:

1 fun runAsync(callback: () -> Unit) {
2     ...
3     callback()
4 }

这个用法相当明确。完成一些转换后(后续会看到的),函数的调用方式可以得到简单化:

1 runAsync { toast("Finished") }

Kotlin语言的另一个出色方面是,允许用lambda表达式编写接口,这样可以巨大地简化代码。举例说明更易明白,假设要编写视图的典型setOnClickListener()方法。

在Java语言中,接口代码类似这样:

1 public interface OnClickListener {
2   void onClick(View v);
3 }

然后,需要编写匿名类实现这个接口:

1 view.setOnClickListener(new OnClickListener() {
2   @Override
3   public void onClick(View v) {
4     Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show();
5   }
6 });

这段代码转换到Kotlin语言(用Anko toast函数)会是这样:

1 view.setOnClickListener(object : OnClickListener {
2   override fun onClick(v: View) {
3     toast("Click")
4   }
5 })

如前所述,Kotlin语言允许对Java语言类库进行一些优化,任何有接口的函数都可以由函数替代。就像定义setOnclickListener()方法那样去运行:

1 fun setOnClickListener(listener: (View) -> Unit)

Lambda表达式由箭头左侧函数的参数(在圆括号里的内容)定义的,将值返回到箭头右侧。在这个例子中,得到的View返回给Unit(无参数)。按此思路,可以上述代码略做简化:

1 view.setOnClickListener({ view -> toast("Click")})

美妙的差异!在定义函数时,必须在箭头的左侧用方括号,并指定参数值,而函数的执行代码在箭头右侧。如果左侧不使用参数,甚至可以省去左侧部分:

1 view.setOnClickListener({ toast("Click") })

如果函数的最后一个参数是一个函数的话,可以将作为参数的函数移到圆括号外面:

1 view.setOnClickListener() { toast("Click") }

最终,如果函数是唯一的参数,还可以去掉圆括号:

1 view.setOnClickListener { toast("Click") }

与初期的Java语言代码相比,代码量小于原来的五分之一,且更容易理解。这实在是令人印象深刻。Anko给一个(本质上说是函数名的)简化版本,由前面展示过的实现方法的扩展函数组成:

1 view.onClick { toast("Click") }

扩展编程语言

多亏有这些转换,可以创建自己的生成器(builder)和代码块。Kotlin语言标准库提供一些像with那样有趣的函数。下面是更简单的实现方式:

1 inline fun <T> with(t: T, body: T.() -> Unit) { t.body() }

这个函数会获取一个类型T的对象和作为扩展函数使用的函数。实现的过程仅仅解决了对象,并让对象执行函数。由于函数的第二个参数是另一个函数,所以可以将其移到括号外面。这样可以直接使用对象的this关键字创建代码块,还能够直接使用对象的公共属性和函数:

1 with(forecast) {
2     Picasso.with(itemView.ctx).load(iconUrl).into(iconView)
3     dateView.text = date
4     descriptionView.text = description
5     maxTemperatureView.text = "${high.toString()}º"
6     minTemperatureView.text = "${low.toString()}º"
7     itemView.onClick { itemClick(forecast) }
8 }

总结

Lambda表达式的能量在于我们的想象力。如果没有用过函数式编程方法,就需要大量的实践,这样做是值得的。如果你要进一步学习lambda表达式和Kotlin相关内容,可从我编写的书中获得

时间: 2024-12-30 09:12:46

释放Android的函数式能量(I):Kotlin语言的Lambda表达式的相关文章

Java 终于有 Lambda 表达式啦~Java 8 语言变化&mdash;&mdash;Lambda 表达式和接口类更改【转载】

原文地址 en cn 下载 Demo Java? 8 包含一些重要的新的语言功能,为您提供了构建程序的更简单方式.Lambda 表达式 为内联代码块定义一种新语法,其灵活性与匿名内部类一样,但样板文件要少得多.接口更改使得接口可以添加到现有接口中,同时又不会破坏与现有代码的兼容性.本文将了解这些更改是如何协同工作的. Java 8 的最大变化在于添加了对 lambda 表达式 的支持.Lambda 表达式是可按引用传递的代码块.类似于一些其他编程语言中的闭包:它们是实现某项功能的代码,可接受一个

Java8函数式编程(一):Lambda表达式类型与常用函数接口

[TOC] 1 前言 最近在看一些开源项目的源码,函数式编程风格的代码无处不在,所以得要好好学一下了. 2 Lambda表达式类型 无参数: Runnable noArguments = () -> System.out.println("Hello World!"); noArguments.run(); 一个参数: UnaryOperator<Boolean> oneArgument = x -> !x; System.out.println(oneArgu

Kotlin语言深入解析

课程介绍:在2017年的Google I/O大会上,Google正式宣布Kotlin将成为Android开发的官方支持语言.一时间,关于Kotlin的相关介绍如雨后春笋般涌现出来,Kotlin也很快成为近几个月来最为火热的开发语言之一.但值得一提的是,Kotlin出现至今已经有了几年的时间,甚至有不少公司的Android App已经部分或是全部采用Kotlin进行了开发,这得益于Kotlin精巧的设计.优雅的语法以及与Java 100%的互操作性.与Java相比,Kotlin是一门年轻的语言,但

Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)

作者:Antonio Leiva 时间:Jan 5, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin/ 由于Lambda表达式允许更简单的方式建模式函数,所以它是Kotlin和任何其他现代开发语言的最强工具之一. 在Java6中,我们仅能下面方法这样做:通过用单一方法声明接口,并用匿名对象实现那些接口. Lambda表达式特别是在Kotlin中能定义的方式,为我们开启无线可能的世界.在接下来的内容中,我们将了解这些用法. Kotlin的Lamb

深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

最近看了一下java 8的一些新特性,其中最重要的莫过于Lambda表达式了,通过一阵子的学习,原本准备自己写一篇博客的,后来阅读了一位学长翻译过来的博客(原文是Brain Goetz的State of Lambda,下面会给出原文链接),觉得写的十分完美,把我想要写的和我没想到的都罗列了出来,就把这个分享给大家了. 注:原译文见  http://lucida.me/blog/java-8-lambdas-insideout-language-features/ 英语原版见:http://cr.

[转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features 本文谢绝转载,如需转载需征得作者本人同意,谢谢. -------------------------------------内容分割线--------------------------------------------------------- 关于 本文是深入

[二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口

函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type used to indicate that an interface * type declaration is intended to be a <i>functional interface</i> as * defined by the Java Language Specificat

Java函数式编程和lambda表达式

为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于某种语法或调用API去进行编程.例如,我们现在需要从一组数字中,找出最小的那个数字,若使用用命令式编程实现这个需求的话,那么所编写的代码如下: public static void main(String[] args) { int[] nums = new int[]{1, 2, 3, 4, 5,

Lambda表达式与函数式接口

Lambda表达式的类型,也被称为目标类型(targer type),Lambda表达式的目标类型必须是"函数式接口(functional interface)".函数式接口代表只包含一个抽象方法的接口.函数式接口可以包含多个默认方法.类方法,但只能声明一个抽象方法. 如果采用匿名内部类的语法来创建函数式接口,则只需要实现一个抽象方法,在这种情况下即可采用Lambda表达式来创建对象.该表达式创建出来的对象的目标类型就是这个函数式接口. Java 8 专门为函数式接口提供了@Funct