可变结果不是应该的

时间:2018-11-18 17:02:43

标签: kotlin

我有这三个实现,(应该)做的基本相同:返回Android exoplayer的当前位置或以整数返回0。 但是只有nr。 1件作品。 Nr。即使player实例化,2和nr.3始终返回0。这是预期的行为吗?

1。

private var playbackPosition = 0
    get() {
        return if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
    }

2。

private var playbackPosition = if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000

3。

private var playbackPosition = when(player)  {
    null -> 0
    else -> player?.currentPosition?.toInt() as Int / 1000
} 

2 个答案:

答案 0 :(得分:1)

数字1是get函数的实现,并在您每次访问变量时调用。

数字2和3初始化变量,并且右侧仅在变量创建时调用一次。表示播放位置仅计算一次。

该行为的工作方式与设计相同。如果每次访问变量都需要新的职位,则必须使用自己的getter函数。

答案 1 :(得分:1)

由于这个问题,我假设您对Kotlin和/或Java不那么熟悉,所以我将解释两者之间的区别。

首先,您需要了解函数与变量/常量之间的区别。调用函数时,结果可能会有所不同(假定它不是void / Unit),但是变量在更新之前具有固定的结果。拿这个:

var toggle = Random().nextBoolean()
var dependent = if(toggle) 0 else 1
toggle = !toggle

如果在切换开关之前和之后打印变量,则变量不会更改。分配后,它将保持该值不变,直到有人对其进行更新。因此,如果添加打印语句,则将是相同的。让我们对此进行扩展:

var toggle: Boolean = Random().nextBoolean()

fun someFunction() : Int = (if(toggle) 0 else 1).also { toggle = !toggle }

这里的also块是一个扩展函数,可以让您执行操作,但仍返回它被调用的变量。此处,返回1或0,并且翻转切换。如果您两次拨打此电话,则会看到不同的结果。这是因为您会根据条件获得不同的值。再次,您看到该值即使切换也不会改变。

TL; DR:变量具有给定值,直到更改为止。返回值的方法可以根据条件而改变,因为每次调用时都会更新。

现在,这对您的代码意味着什么?

首先,对于第一个代码段,应改用val。那样的Kotlin真的很好。如果您覆盖val的getter,则无需初始化它。这称为备用字段。

无论如何,

private val playbackPosition
    get() {
        return if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
    }

根据播放器变量调用时的返回值。还有其他示例:

private var playbackPosition = if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000


private var playbackPosition = when(player)  {
    null -> 0
    else -> player?.currentPosition?.toInt() as Int / 1000
} 

在定义它们时设置值。您也可以将其更改为val;它们不会自动重新分配。

初始赋值(即您那里的代码)仅运行一次,这就是类初始化的时间。如果变量在方法内部,则在调用该方法时将初始化该变量。 lateinit vars可在以后设置,但初始分配仅运行一次。对于任何更改,您都需要对其进行更新。

但是,这是方法派上用场的地方。根据所拥有的内容,您还可以以某种方式创建一个后备字段,即“缓存”。除非对象创建很繁琐,否则这不是必需的。您不需要担心整数之类的简单问题。使用返回值(在您的情况下为getter)的方法有点像这样做:

var x: Int = updateValue()

fun updateValue() : Int = if ... // alternatively does x = instead of returning an int

...
x = updateValue()
x.let { foo bar }

尽管那是做事的相当困难的方法。


  

但是只有Nr。 1件作品。 Nr。尽管播放器已实例化,但2和Nr.3始终返回0。

如果您在2和3的所有时间都得到0,则意味着player == null 变量初始化时,但是当getter for第一个例子被称为。

  

那是预期的行为吗?

考虑代码,是的。这是设计使然。

TL; DR:同样,创建条件(即玩家== null)发生变化时,变量不会自动更新。您将需要手动更新它,或者对变量使用方法。