Kotlin:引用自己/内部的匿名对象(通过这个)

问题描述 投票:3回答:1

TL; DR这些object : someClass{ }匿名对象无法通过this访问自身(导致外部对象)。我该如何访问它?

更长的解释:

对于我的片段,我需要一个PreDrawListener。我在onCreateView中调用它。执行时,我希望之后删除监听器。所以Java的做法就是这样的

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,    

  val treeObserver = layout.viewTreeObserver

  treeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
     override fun onPreDraw(): Boolean {
        layout.viewTreeObserver.removeOnPreDrawListener(this)
        ...
     }
  }

问题是,当看看removeOnPreDrawListener(this)时,this对象不是听众,而是myFragment$onCreateView$1@f019bf0

或者,我可以访问this@MyFragment,它直接返回对Fragment的引用。

尽管如此,这些选项似乎都不是我的PreDrawListener。如何从内部访问它(如果有的话)?

android kotlin this anonymous-class
1个回答
3
投票

老实说,我没有看到你的问题。

匿名中的this指的是班级本身,但他们从来没有名字。您无法使用名称创建匿名类。为了演示这个,我写了一些示例代码:

class TheClass{
    fun run(){
        val anon = object: Runnable {
            override fun run() {}
        }
        println(anon::class.java.simpleName)
        println(anon::class.java.name)
    }
}

哪个印刷品:

run$anon$1
com.package.TheClass$run$anon$1

现在,这很好,但它仍然看起来不像你的。但是你看到它匹配包含的类,方法,变量,最后是美元符号,表示它是一个匿名的内部类。这适用于第二个,即完整的。第一个只打印短名称,即方法,var名称,以及显示它的匿名函数的美元符号。

如果您对出现数字的美元符号感兴趣,请参阅this。 Ť

让我们扩展它并抛弃变量。显然,这是一个可怕的代码(远远没有内存效率,但它是一个演示所以无关紧要):

class TheClass {
    fun run(){
        println(object: Runnable {
            override fun run() { }
        })
    }
}

这将打印并匹配您的模式:

com.package.TheClass$run$anon$1

你已经看到了这种模式;现在你可以开始“解码”你得到的哈希:

myFragment // inside myFragment
$onCreateView // Inside a function
$1 // There is an anonymous class with a specific identifier
@f019bf0 // This is standard everywhere; just look up Object.toString()

我刚刚尝试证明的是:this确实引用了您创建的匿名函数。匿名函数是匿名的。他们没有名字。他们使用$number作为标识符。所以如果你有这个代码:

treeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
    override fun onPreDraw(): Boolean {
       layout.viewTreeObserver.removeOnPreDrawListener(this)
       ...
    }
 }

this将引用监听器,即使打印该类可能会打印看起来令人困惑的东西。如果有什么东西被打破了,那不是因为this没有提到听众(因为它确实如此)

此外,您的代码编译良好。那里也没有类型不匹配。如果它引用了另一个对象,如果你将this传递给需要OnPreDrawListener的方法,它将无法工作。


您将在Java中使用相同的代码获得不同的结果。这是因为Kotlin将匿名函数编译为Class$function$number,Java将其编译为Class$number。如果它在嵌套类中,它将在Kotlin中显示为Outer$Inner$function$number,在Java中显示为Outer$Inner$number

编译器的不同之处在于会产生不同的名称; Java排除了函数,Kotlin包含它。它在.class文件名中,所以如果你构建你的项目并查看文件浏览器中的文件名,无论你有什么操作系统(不要看IntelliJ。它会为你反编译文件。记住,你只是看着对于名称,IntelliJ通过将.class文件合并为单个文件以匹配原始源来解决这个问题


就像最后的元,我打印类而不是打印对象。接口没有重写的toString方法,这意味着它默认为Object上的那个,它返回getClass().getName() + "@" + Integer.toHexString(hashCode());(原始代码可以找到here)。 println(this)println(this.toString())相同,后者在Object中调用toString方法,该方法打印类名。 println(this)与打印对象或打印类相同

© www.soinside.com 2019 - 2024. All rights reserved.