代码之家  ›  专栏  ›  技术社区  ›  Tobias Reich

Kotlin:从自身/内部引用匿名对象(通过此)

  •  3
  • Tobias Reich  · 技术社区  · 6 年前

    太长,读不下去了 object : someClass{ } 匿名对象无法通过 this (结果是 ). 如何访问它?

    详细说明:

    对于我的片段,我需要一个预先绘制的侦听器。我称之为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) myFragment$onCreateView$1@f019bf0

    或者我可以访问 this@MyFragment 直接返回对片段的引用。

    不过,这些选择似乎都不是我的选择 PreDrawListener . 如何从内部访问它(如果有的话)?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Zoe - Save the data dump 张群峰    6 年前

    我真的不明白你的问题。

    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 name,以及显示匿名函数的美元符号。

    如果您对带数字的美元符号出现的原因感兴趣,请参阅 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()
    

    我想证明的是: $number 作为标识符。如果你有这个代码:

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

    将引用侦听器,即使打印类可能会打印看起来很混乱的内容。如果有什么东西坏了,那不是因为 不引用侦听器(因为它引用了)

    而且,您的代码编译得很好。也没有类型不匹配。如果它引用了另一个对象,如果你通过了它就不起作用了 一个需要 OnPreDrawListener


    在Java中使用相同的代码会得到不同的结果。这是因为Kotlin将匿名函数编译为 Class$function$number ,Java将其编译到 Class$number . 如果它在嵌套类中,它将显示为 Outer$Inner$function$number 在科特林,和 Outer$Inner$number 在爪哇。

    编译器中的差异导致了不同的名称;Java排除了函数,而Kotlin包含了函数。在房间里 .class 不要看IntelliJ . 它将为您反编译文件。记住,您只需要查找名称,IntelliJ会将.class文件合并到一个文件中,以匹配原始源代码,从而将名称弄乱)


    getClass().getName() + "@" + Integer.toHexString(hashCode()); here ). println(this) 与相同 println(this.toString()) 打印(本)