代码之家  ›  专栏  ›  技术社区  ›  Louis Wasserman

是否可以编写“双重”扩展方法?

  •  4
  • Louis Wasserman  · 技术社区  · 7 年前

    在Kotlin中,可以编写

    class A {
      fun B.foo()
    }
    

    然后写 with (myA) { myB.foo() }

    A ,而不是?我的用例是写作

    with (java.math.RoundingMode.CEILING) { 1 / 2 }
    

    1 ,我想补充一点 operator fun Int.div(Int) RoundingMode

    3 回复  |  直到 7 年前
        1
  •  2
  •   Oleksandr.Bezhan    7 年前

    不,不可能。 operator div Int 作为接受者。

    RoundingMode 作为接收器,因为只能有单功能接收器。

    不过,你能做的就是 Pair<RoundingMode, Int> 作为接收者:

    operator fun Pair<RoundingMode, Int>.div(i: Int): BigDecimal =
            BigDecimal.valueOf(second.toLong()).divide(BigDecimal.valueOf(i.toLong()), first)
    
    with(RoundingMode.CEILING) {
        println((this to 1) / 2) // => 1
    }
    
        2
  •  1
  •   Coder-Man    7 年前

    那是不可能的, Int div 部门

    但你可以这样写:

    fun RoundingMode.div(x: Int, y: Int): Int {
        return if (this == RoundingMode.CEILING) {
            Math.ceil(x.toDouble() / y.toDouble()).toInt()
        } else {
            Math.floor(x.toDouble() / y.toDouble()).toInt()
        }
    }
    
    fun main(args: Array<String>) {
        with(java.math.RoundingMode.CEILING) {
            println(div(1,2))
        }
    }
    
        3
  •  0
  •   lucasls    7 年前

    不可能的原因有:

    1. div 已在中定义 Int

    但是,您可以使用

    1. 上下文类和扩展lambda(例如。 block: ContextClass.() -> Unit
    2. 中缀函数(例如使用 15 div 4 15 / 4 )

    请参见下面的示例:

    class RoundingContext(private val roundingMode: RoundingMode) {
        infix fun Int.div(b: Int): Int {
            val x = this.toBigDecimal()
            val y = b.toBigDecimal()
    
            val res = x.divide(y, roundingMode)
    
            return res.toInt()
        }
    }
    
    fun <T> using(roundingMode: RoundingMode, block: RoundingContext.() -> T): T {
        return with(RoundingContext(roundingMode)) {
            block()
        }
    }
    
    // Test
    fun main(args: Array<String>) {
        using(RoundingMode.FLOOR) {
            println(5 div 2) // 2
        }
        val x = using(RoundingMode.CEILING) {
            10 div 3
        }
        println(x) // 4
    }
    

    希望有帮助!