Function Literals and Reference to Enclosing Class

Do function literals in Kotlin always keep an implicit reference to their enclosing class like anonymous classes in Java or do they have the same optimization as Java 8's lambdas where there will be only one instance of the anonymous function if it does not reference anything from its enclosing scope?

I wondered about it because on Android one has to be careful with anonymous classes (and rather create static classes) to not accidentally hold onto an activity which should be garbage collected.

2 Likes

There's only one instance of the anonymous function which doesn't capture anything.

1 Like

Good to know!

I was just reading the following blog post: https://techblog.badoo.com/blog/2014/08/28/android-handler-memory-leaks/
The interesting part was about the WeakReference to the TextView. As far as I understand it would be impossible to use a function literal in Kotlin that captured its environment by weak references and one would need a static inner class (or a nested class in Kotlin’s terms) just like in Java.

It got me thinking if a syntactic way to express that all or some captured variables should be weak references (somewhat similar to C++11’s lambda capture lists) might be worthwhile to add to Kotlin. I know that it’s more of hypothetical design question :stuck_out_tongue: but I’m still curious about your thoughts.


Edit:

I guess I could do something like the following: http://kotlin-demo.jetbrains.com/?publicLink=108968034636621625775-561465701
Ore here as static text:

import java.lang.ref.WeakReference

fun main(args : Array<String>) {
  val textView = View(“Hello World”)
  val f = weakref(textView) { tvRef ->
  val tv = tvRef.get()
  println(tv?.field)
  }
  f()
}

fun weakref(v0: View, f: (WeakReference<View>) -> Unit): () -> Unit {
  val w0 = WeakReference<View>(v0)
  return { f(w0) }
}

fun weakref(v0: View, v1: View, f: (WeakReference<View>, WeakReference<View>) -> Unit): () -> Unit {
  val w0 = WeakReference<View>(v0)
  val w1 = WeakReference<View>(v1)
  return { f(w0, w1) }
}

class View(val field: String)


It’s not generic but without something like macros that’s probably the best way to approximate capture lists. I hope the code really has the semantics I wished for :p.


Edit2:

I just noticed I’d have to cast anyway, so I might just as well use Any instead of View in the definition of weakref and write the body like so:

val f = weakref(textView) { tvRef ->   val tv = tvRef.get() as TextView?   println(tv?.field)   }

2 Likes

Having one or multiple instance(s) per function literal and keeping a reference to the enclosing class instance from that literal are different concerns, no?