函数定义:fun vs val [英] Function definition: fun vs val

查看:180
本文介绍了函数定义:fun vs val的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很好奇在Kotlin中定义成员函数的建议方法是什么.考虑以下两个成员函数:

I'm curious about what is the suggested way to define member functions in Kotlin. Consider these two member functions:

class A {

  fun f(x: Int) = 42

  val g = fun(x: Int) = 42

}

这些似乎可以完成相同的任务,但是我发现了细微的差别.

These appear to accomplish the same thing, but I found subtle differences.

例如,基于val的定义在某些情况下似乎更灵活.也就是说,我无法找到一种直接的方法来将f与其他功能组合在一起,但是我可以与g组合在一起.为了弄清楚这些定义,我使用了 funKTionale 库.我发现它无法编译:

The val based definition, for instance, seems to be more flexible in some scenarios. That is, I could not work out a straight forward way to compose f with other functions, but I could with g. To toy around with these definitions, I used the funKTionale library. I found that this does not compile:

val z = g andThen A::f // f is a member function

但是,如果将f定义为指向同一函数的val,它将可以正常编译.为了弄清楚发生了什么,我要求IntelliJ为我显式定义::fg的类型,这给了我这个:

But if f were defined as a val pointing to the same function, it would compile just fine. To figure out what was going on I asked IntelliJ to explicitly define the type of ::f and g for me, and it gives me this:

val fref: KFunction1<Int, Int> = ::f

val gref: (Int) -> Int = g

因此,一个类型为KFunction1<Int, Int>,另一个类型为(Int) -> Int.显而易见,这两个函数都代表类型为Int -> Int的函数.

So one is of type KFunction1<Int, Int>, the other is of type (Int) -> Int. It's easy to see that both represent functions of type Int -> Int.

这两种类型有什么区别,在什么情况下重要?我注意到,对于顶层函数,我可以使用任何一种定义对其进行精细组合,但是为了使上述组合得以编译,我必须像这样编写它:

What is the difference between these two types, and in which cases does it matter? I noticed that for top-level functions, I can compose them fine using either definition, but in order to make the aforementioned composition compile, I had to write it like so:

val z = g andThen A::f.partially1(this)

即我必须先将其部分应用于this.

i.e. I had to partially apply it to this first.

由于使用val作为函数时不必麻烦,所以有理由为什么我应该使用fun定义非Unit成员函数吗?我缺少的性能或语义上有区别吗?

Since I don't have to go through this hassle when using vals for functions, is there a reason why I should ever define non-Unit member functions using fun? Is there a difference in performance or semantics that I am missing?

推荐答案

Kotlin完全是关于Java互操作性的,将函数定义为val会在互操作性方面产生完全不同的结果.以下Kotlin类:

Kotlin is all about Java interoperability and defining a function as a val will produce a completely different result in terms of the interoperability. The following Kotlin class:

class A {
  fun f(x: Int) = 42
  val g = fun(x: Int) = 42
}

实际上等效于:

public class A {
  private final Function1<Integer, Integer> gref = new Function1<Integer, Integer>() {
    @Override
    public Integer invoke(final Integer integer) {
      return 42;
    }
  };

  public int f(final int value) {
    return 42;
  }

  public Function1<Integer, Integer> getG() {
    return gref;
  }
}

如您所见,主要区别在于:

As you can see, the main differences are:

  1. fun f只是一种常用方法,而val g实际上是一个高阶函数,它返回另一个函数
  2. val g涉及创建一个新类,如果您以Android为目标,那么这是不好的
  3. val g需要不必要的装箱和拆箱
  4. val g不能从Java轻松调用:Kotlin中的A().g(42)与Java中的new A().getG().invoke(42)
  1. fun f is just a usual method, while val g in fact is a higher-order function that returns another function
  2. val g involves creation of a new class which isn't good if you are targeting Android
  3. val g requires unnecessary boxing and unboxing
  4. val g cannot be easily invoked from java: A().g(42) in Kotlin vs new A().getG().invoke(42) in Java

更新:

关于A::f语法.编译器将为每次 A::f事件生成一个额外的Function2<A, Integer, Integer>类,因此以下代码将生成两个额外的类,每个类具有 7个方法:

Regarding the A::f syntax. The compiler will generate an extra Function2<A, Integer, Integer> class for every A::f occurrence, so the following code results in two extra classes with 7 methods each:

val first = A::f
val second = A::f

Kotlin编译器目前不足以优化此类内容.您可以在此处对此问题进行投票 https://youtrack.jetbrains.com/issue/KT-9831 .如果您感兴趣,以下是每个类在字节码中的显示方式: https://gist.github .com/nsk-mironov/fc13f2075bfa05d8a3c3

Kotlin compiler isn't smart enough at the moment to optimize such kind of things. You can vote for the issue here https://youtrack.jetbrains.com/issue/KT-9831. In case you are interested, here is how each class looks in the bytecode: https://gist.github.com/nsk-mironov/fc13f2075bfa05d8a3c3

这篇关于函数定义:fun vs val的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆