Android KTX:如何覆盖 Kotlin 添加的 属性 扩展

Android KTX: how to override Kotlin added property extension

我正在尝试覆盖 Kotlin 中的 View.setRotation() 方法。

由于AndroidKTX已经提供了属性分机"rotation",来电者只需拨打

viewObject.rotation = 90.0f

旋转视图。

但是,我想在用户改变旋转时添加一些额外的操作,比如

override fun setRotation(newRotation: Float) {
    if (rotation == newRotation)
        return
    rotation = newRotation
    doSomethingElse()
}

这会因为 Whosebug 错误而崩溃。

所以,我必须添加一些额外的代码来实现目标:

    private var _rotation: Float = 0.0f
    override fun setRotation(newRotation: Float) {
        if (_rotation == newRotation) {
            return
        }
        _rotation = newRotation
        updateRotationInternally()
    }

    private fun updateRotationInternally() {
        super.setRotation(_rotation)
        doSomethingElse()
    }

这行得通,但我想知道是否还有其他更优雅的方法,比如 "override the property extension setter"?

我不同意您实施的一个方面:您的 return 快捷方式。您假设使用现有旋转值调用 setRotation() 无效。如果 View 的官方 Google 版本确实如此,我不会感到惊讶,但据我们所知,这在某些 Oppo 设备 运行 修改后的版本上并不是一个安全的假设Android 8.0。尽量不要假设你没有写的东西的行为。如果你想在新旧旋转相等时跳过doSomethingElse(),那很好。

我猜你的 setRotation() 函数在 View 的某个子类中。如果是这样,并考虑到我的上述抱怨,这是我能想到的最简单的方法:

class Bar : View() {
  override fun setRotation(f: Float) {
    val needSomething = getRotation() != f

    super.setRotation(f)

    if (needSomething) doSomethingElse()
  }

  fun doSomethingElse() {
    println("got here!")
  }
}

我的整体测试代码是在 a Kotlin scratchpad 中完成的(在 Android 之外),所以我用一个假的 View 实现和假的 rotation 扩展 [=34] 进行了测试=]:

open class View {
  private var r: Float = 0.0f

  open fun setRotation(f: Float) {
    r = f
  }

  fun getRotation() = r
}

var View.rotation: Float
  get() = getRotation()
  set(value) = setRotation(value)

class Bar : View() {
  override fun setRotation(f: Float) {
    val needSomething = getRotation() != f

    super.setRotation(f)

    if (needSomething) doSomethingElse()
  }

  fun doSomethingElse() {
    println("got here!")
  }
}

fun main() {
  val bar = Bar()

  bar.rotation = 15.0f
  bar.rotation = 15.0f
}

如果你 运行 在那个暂存器中,你会看到 got here 打印在控制台上一次,表明当我们成功更新扩展 属性 两次时,我们跳过了 getSomethingElse() 在第二次调用时,因为新旧旋转相同。