代码之家  ›  专栏  ›  技术社区  ›  lolo.io

Kotlin,将扩展函数添加到具有其他接收器类型的类中

  •  0
  • lolo.io  · 技术社区  · 1 年前

    有一个科特林的把戏我一直想实现,但我不确定这是可能的。

    我们可以给一个类添加一个扩展函数,但有另一个接收器类型吗?

    作为一个例子,让我们想象一下我们想要添加一个函数 launchInViewModelScope() 到抽象类 ViewModel 。但我们希望此函数只能由调用 Flow<*> .

    ViewModel Flow 是kotlin的一部分,所以我们必须使用扩展函数。

    当在类主体内部添加扩展函数时,这种行为是可能的,但这里我们不能在内部添加函数 ViewModel 身体

    我正在寻找一个解决方案来写这样的东西:

    ViewModel.Flow<*>.launchInViewModelScope() { /* doWork */} 
    
    • 当然,我不想创建的子类 ViewModel ,那太容易了:D。
    • 我也不想向ViewModel添加配套对象,因为我需要访问 ViewModelScope 例子

    以下是带有代码的同一问题的框架:

    /** SUPPOSE A AND B  ARE DEFINED IN A LIBRARY **/ 
    abstract class A {
        fun B.doSomeThing() {
            println("something")
        }
    }
    
    
    class B {
    }
    
    /*********************************************/
    
    
    
    // Is there an existing way to achieve something like this ?
    fun A.B.doSomeThingElse() {
        println("somethingElse")
    }
    
    
    // That can allow me to do this :
    class AImpl: A() {
        val b = B()
        fun main() {
            // This works as expected
            b.doSomeThing()
            
            // I want this to work :
            b.doSomeThingElse()
        }
    }
    
    class C {
        val b = B()
        fun main() {
            // I want this NOT to work :
            b.doSomeThingElse()
        }
    }
    
    1 回复  |  直到 1 年前
        1
  •  1
  •   Sweeper    1 年前

    Context receivers 是您需要的功能。通过 -Xcontext-receivers 编译器选项,以启用此实验功能。然后你可以写:

    context(A)
    fun B.doSomeThingElse() {
        println("somethingElse")
    }
    

    您有权访问的实例 A 在功能体中,就好像它是扩展接收器一样。如果你需要毫不含糊地提及它,你可以说 this@A .