Переменный результат не тот, который должен быть - PullRequest
0 голосов
/ 18 ноября 2018

У меня есть эти три реализации, которые (должны) делать по сути то же самое: возвращать текущую позицию экзоплеера Android или 0 как целое число.Но только номер1 работает.Nr.2 и номер 3 всегда возвращают 0, даже если создается экземпляр player.Это ожидаемое поведение?

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 голосов
/ 19 ноября 2018

Из-за вопроса, я полагаю, вы не очень знакомы с 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. Котлин действительно такой хороший; если вы переопределяете метод получения значения val, вам не нужно его инициализировать. Это называется вспомогательные поля.

В любом случае, это:

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 переменные могут быть установлены позже, но начальное назначение выполняется только один раз. Для любых изменений вам необходимо обновить его.

Однако, здесь методы пригодятся. В зависимости от того, что у вас есть, вы также можете создать вспомогательное поле, «кеш». Это не нужно, если создание объекта не является тяжелым. Вам не нужно беспокоиться об этом для чего-то такого простого, как целые числа. Использование метода, который возвращает значение (в вашем случае, получателя), выглядит примерно так:

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, хотя игрок создан.

Если вы получаете 0 все время для 2 и 3, это означает player == null , когда переменные были инициализированы , но оно не было нулевым, когда вызывался метод получения для первого примера.

Это ожидаемое поведение?

Учитывая код, да. Это по замыслу.

TL; DR: Опять же, переменные не обновляются автоматически при изменении условия создания (т. Е. Player == null). Вам нужно будет либо обновить его вручную, либо использовать методы над переменными.

0 голосов
/ 18 ноября 2018

Номер 1 является реализацией функции get и вызывается каждый раз, когда вы обращаетесь к переменной.

Числа 2 и 3 инициализируют переменную, а правая сторона вызывается только один раз во время создания переменной,Означает, что позиция воспроизведения рассчитывается только один раз.

Поведение работает, как задумано.Если вам нужна новая позиция каждый раз, когда вы обращаетесь к переменной, вы должны использовать собственную функцию получения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...