Идея умного приведения состоит в том, чтобы помочь вам избежать использования as
или as?
для явного приведения того, что уже было проверено. Что касается пунктов, указанных выше, вот несколько примеров.
- val локальные переменные - поскольку val является окончательным (не может быть изменено), после выполнения проверки переменная может быть умно преобразована как он не может измениться снова.
val a: Int? = 2
if (a is Int) {
// 'a' is smart cast to Int
val b = a * 2 // b is also Int
}
- свойства val - при прямом доступе (через геттер по умолчанию) возможно умное приведение. Если через пользовательский метод получения, это не потому, что мы не можем знать, что он был изменен.
class Test {
val a: Int? = 2;
}
class TestGetter {
val a: Int? = 2
get() = field * 2
}
// Usage
val test = Test()
val testGetter = TestGetter()
if (test.a is Int) {
// 'test.a' is smart cast to Int
val b = test.a * 2
}
if (testGetter.a is Int) {
// smart cast is impossible, 'testGetter.a' is still Int?
val b = testGetter.a * 2 // can't happen because we don't know whether 'a' was changed by the custom getter or not (the getter could give unstable values)
}
- var локальные переменные - если переменная не изменилась между проверкой и использованием, не захвачено в лямбде, которая его изменяет, и не является локальным делегированным свойством;
var a: Int? = 2
if (a is Int) {
// 'a' was not changed, so it can be smart cast to Int
val b = a * 2 // b is also Int
}
var c = 4
if (c is Int) {
c = null
// 'c' was changed between the check and the usage, we cannot smart cast it anymore
val b = c * 2 // won't work
}
свойства var - var всегда может быть изменен чем-то другим в коде, поэтому умное приведение не будет работать.
class Example {
var a: Int? = 2
fun test1() {
if (a is Int) {
// smart cast is impossible because we don't know whether 'a' was changed by some other code/function
val b = a * 2 // won't work
}
}
}
Что касается использования as
, если вы посмотрите на последний пример:
class Example {
var a: Int? = 2
fun test1() {
if (a is Int) {
// smart cast is impossible because we don't know whether 'a' was changed by some other code/function
val b = a as Int * 2 // this WILL work because we forcefully cast it to Int, but if a is null there will be an exception in runtime
}
}
}
Вы также можете использовать as?
, когда не уверены может ли var быть приведено к чему-либо или нет. Если нет, он просто даст вам ноль. Например:
val a: Double = 2.0
val b = a as? String // 'b' will be 'String?', in this case initialized to 'null' since 'a' cannot be cast to it
val c: Int? = 2
val d = c as? Int // 'd' will be '2' but still 'Int?' since 'as?' always makes the variable nullable
Надеюсь, примеры помогли, дайте мне знать, если мне нужно что-то уточнить.