kotlin 扩展类的功能_Kotlin Magic功能您需要知道的一切

kotlin 扩展类的功能

In this article, we’ll take a look at the most common “magic” use of functions in Kotlin.

在本文中,我们将介绍Kotlin中最常见的“神奇”功能用法。

扩展功能 (Extension Functions)

Let’s start simple: extending classes without inheritance. We can, without changing the class Stringand all the packages that use it, extend this class by adding a new method or property (field). Let's have a method deleteSpaces():

让我们开始简单: 扩展没有继承的类 。 我们可以在不更改String类和所有使用它的包的情况下,通过添加新的方法或属性(字段)来扩展此类。 让我们有一个方法deleteSpaces()

And we can use this method as if it were part of a class String. The user will see it like this:

而且我们可以像使用String类那样使用它。 用户将如下所示:

After compilation, this method will look something like this (part of the code has been simplified to make it easier for you to understand the essence):

编译后,此方法将如下所示(部分代码已简化,以使您更容易理解其本质):

From this we can conclude that inside the method deleteSpaces() we have access only to public fields and methods of the class, so that encapsulation is not broken.

由此可以得出结论,在deleteSpaces()方法内部,我们只能访问该类的公共字段和方法,因此封装不会中断。

In addition to Extension Functions in Kotlin, by analogy, there can be Extension Properties:

类似地,除了Kotlin中的扩展功能外,还可以有扩展属性:

Most of the “magic” uses of functions and lambdas in Kotlin, like this one, are nothing more than syntactic sugar, but how convenient!

像这样,在Kotlin中,大多数对函数和lambda的“魔术”用法都不过是语法糖,而是多么方便!

Lambda函数和匿名函数 (Lambda functions and anonymous functions)

In Kotlin, anonymous and lambda functions are functions without a name, but they can also be used as objects. They can be written directly inside the expression, bypassing a separate declaration.

在Kotlin中,匿名函数和lambda函数是没有名称的函数,但是它们也可以用作对象。 它们可以绕过单独的声明直接写在表达式内部。

The syntax for a lambda expression is:

lambda表达式的语法为:

{ arguments -> returned_type
function_body
}

The syntax for declaring an anonymous function is exactly the same as for a regular function, but the first has no name.

声明匿名函数的语法与常规函数完全相同,但是第一个没有名称。

We will talk about the semantic differences between these types of functions later, but now we will consider examples of using lambdas together with higher-order functions.

稍后,我们将讨论这些类型的函数之间的语义差异,但是现在,我们将考虑将lambda与高阶函数一起使用的示例。

高阶函数 (Higher-order functions)

A higher-order function is a function that takes as one of its arguments another function, including a lambda or anonymous function. A striking example of using such functions is a callback.

高阶函数是将另一个函数(包括lambda或匿名函数)作为其参数之一的函数。 使用此类函数的一个显着示例是回调。

Let’s say we have a higher-order function longWork():

假设我们有一个高阶函数longWork()

It takes a function as an argument callback(), but only calls it after the function doSomething(). Using this function:

它使用一个函数作为参数callback() ,但是仅在doSomething()函数之后调用它。 使用此功能:

Here we call the function longWork()and pass it a lambda function as an argument, which it will call later. Koltin allows you to put a lambda outside the brackets if it is the last argument of a function, and also completely remove the brackets if the lambda is the only argument. Also, in most cases, you can remove the return type and replace the arguments with _if they are not used. Here's a shorter version:

在这里,我们调用函数longWork()并将其作为参数传递给lambda函数,稍后将调用该函数。 Koltin允许您将lambda放在方括号之外(如果它是函数的最后一个参数);如果lambda是唯一的参数,则还可以完全删除方括号。 同样,在大多数情况下,如果不使用返回值,则可以删除返回类型,并用_替换参数。 这是一个简短的版本:

And this outwardly resembles not a higher-order function, but a language construct, as, for example, synchronizedin Java. By the way, synchronizedin Kotlin it is built exactly as a higher-order function.

而且从外观上看,它不像高阶函数,而是像Java中synchronized的语言构造。 顺便说一句,在Kotlin中synchronized它完全是作为高阶函数构建的。

This is very convenient for creating so-called DSL (Domain-Specific Languages) — domain-specific languages. Some of the most popular DSLs for Kotlin are Anko (Android UI directly in Kotlin while preserving the convenience of XML markup), Gradle Kotlin DSL (Gradle scripts on Kotlin), kotlinx.html (by analogy with Anko).

这对于创建所谓的DSL(特定于域的语言)(特定于域的语言)非常方便。 Kotlin 最受欢迎的DSL包括Anko (直接在Kotlin中使用Android UI,同时保留XML标记的便利性)Gradle Kotlin DSL ( Kotlin上的 Gradle脚本)kotlinx.html (类似于 Anko )

For example, consider a Kotlin HTML page:

例如,考虑一个Kotlin HTML页面:

This will print to stdout:

这将打印到标准输出:

The main advantage of this DSL is that unlike declarative HTML, Kotlin has variables that can be used to generate a dynamic page. And this is much prettier and more convenient than classical page generation through a concatenation of many strings. In reality, other methods are used to generate HTML markup, this one was shown only as an example of a DSL in Kotlin.

这种DSL的主要优点是,与声明性HTML不同,Kotlin具有可用于生成动态页面的变量。 与通过多个字符串串联而成的经典页面生成相比,这更漂亮,更方便。 实际上,其他方法用于生成HTML标记,该方法仅作为Kotlin中DSL的示例显示。

Another example of using higher-order functions is as analogous to the Streams API from Java:

使用高阶函数的另一个示例类似于Java的Streams API:

更复杂的Lambda (More complex lambdas)

Let’s look at some example code:

让我们看一些示例代码:

Using more complex higher-order functions from the language standard library, you can turn the code above into the following:

使用语言标准库中更复杂的高阶函数,可以将上面的代码转换为以下代码:

As you can see, the method apply()allows you not to write several times builder.append()thanks to the following method prototype:

如您所见,由于以下方法原型,方法apply()允许您多次编写builder.append()

public inline fun <T> T.apply(block: T.() -> Unit): T

public inline fun <T> T.apply(block: T.() -> Unit): T

Here the lambda function blockis an extension method for the type T, in this case for StringBuilder. And append()inside the lambda block is this.append()where thisis the instance of the class StringBuilder.

在这里,lambda功能block是类型T的扩展方法,在这种情况下是StringBuilder 。 在lambda block append()this.append() ,其中thisStringBuilder类的实例。

The method let()works in a similar way, only accepting a slightly different lambda:

let()方法的工作方式类似,只接受稍有不同的lambda:

public inline fun <T, R> T.let(block: (T) -> R): R

public inline fun <T, R> T.let(block: (T) -> R): R

Here, the object reference is passed not as a quality this, but as an explicit method argument, but we did not specify it. In such cases, the compiler automatically names the first argument to the lambda function "it".

在这里,对象引用不是作为this的质量传递的,而是作为显式方法参数传递的,但是我们没有指定它。 在这种情况下,编译器会自动将lambda函数的第一个参数命名为“ it”。

关于未说的一点 (A little about the unsaid)

First, Kotlin, unlike Java, has overloaded operators. So, for example, if a class has a method plus(), then it can be called by an operator +, and a method by get()an operator [].

首先,与Java不同,Kotlin具有重载运算符。 因此,例如,如果一个类具有方法plus() ,则可以由操作符+调用该方法,而可以通过get()操作符[]调用方法。

Secondly, functions in Kotlin can be explicitly marked as inlineor noinline. This modifier tells the compiler whether to inline the function to improve performance or not. But here's the catch: different behavior returnin inlineand noinlinefunction.

其次,可以将Kotlin中的函数显式标记为inlinenoinline 。 该修饰符告诉编译器是否内联函数以提高性能。 但是这里有个noinlineinlinenoinline函数return不同的行为。

In inlinefunctions, it returnwill be produced from the closest noinlinefunction in scope . B noinline- from the function itself. Named solutions solve this problem return.

noinline inline函数中,它的return将由scope中最接近的noinline函数产生。 B noinline来自函数本身。 命名方案解决这个问题return

To make returnfrom the lambda that we pass in the example above to apply(), you can use return@apply.

为了使我们在上面的示例中传递给apply()的lambda产生return ,可以使用return@apply

Named can not only be return, but also break, continue. You can also create your own labels:

命名不仅可以return ,还可以breakcontinue 。 您还可以创建自己的标签:

In addition, there is a function modifier tailrecthat tells the compiler to replace the recursion in the function with a loop if it is written in the return if-then-else functional format. Example:

另外,有一个函数修饰符tailrec ,告诉编译器以循环if-then-else函数格式编写时,用循环替换函数中的递归。 例:

Thirdly, if a method requires an object as arguments, which must be inherited from a class / interface with one abstract method, then a lambda or an anonymous function can be passed to this function, and the compiler itself will create an anonymous class with overriding the abstract method by our lambda. For example, the Android standard library has a method public void setOnClickListener(View.OnClickListener l)where OnClickListeneris an interface with a single method onClick(View v).

第三,如果一个方法需要一个对象作为参数,并且必须使用一个抽象方法从一个类/接口继承该对象,则可以将lambda或匿名函数传递给该函数,并且编译器本身将创建一个具有重写的匿名类。 lambda的抽象方法。 例如,Android标准库具有一个方法public void setOnClickListener(View.OnClickListener l) ,其中OnClickListener是具有单个方法onClick(View v)的接口。

The lambda passed in the view setOnClickListener { doSomething() }will be compiled into an anonymous class that implements the interface OnClickListener, where our lambda will turn into a method onClick(View v).

在视图setOnClickListener { doSomething() }传递的lambda将被编译成实现接口OnClickListener的匿名类,在这里我们的lambda将变为onClick(View v)

结果 (Outcome)

This is far from all about functions in Kotlin, only the most commonly used. With its “magic” functions, Kotlin makes writing and, most importantly, reading code much easier. Ease of writing and safety are two of the most important differences between Kotlin and Java, created back in 1995 (!). At that time, the convenience and safety of the code were only dreamed of.

这与Kotlin中仅是最常用的功能完全无关。 凭借其“魔术”功能,Kotlin使编写和(更重要的是)阅读代码变得更加容易。 易于编写和安全性是Kotlin和Java(创建于1995年!)之间最重要的两个区别 那时,人们只是梦想着代码的方便性和安全性。

阅读更多 (Read More)

If you found this article helpful, click the💚 or 👏 button below or share the article on Facebook so your friends can benefit from it too.

如果您认为本文有帮助,请单击下面的click或💚按钮或在Facebook上分享该文章,以便您的朋友也可以从中受益。

翻译自: https://medium.com/dev-genius/kotlin-magic-functions-everything-you-need-to-know-63e9957eea11

kotlin 扩展类的功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值