https://kotlinlang.org logo
Title
b

blue

10/19/2021, 11:51 PM
Hi👋, Can someone tell me why the compile error is going away as soon as uncomment the
student as Student
from the below code? Don’t I have to explicitly assign the cast result to a variable to access the
score
property?
abstract class Person(val name: String)
class Student(val score: Int, name: String) : Person(name)
class Teacher(name: String) : Person(name)

fun someFun(student: Person) {
//  student as Student
    
    println(student.score)
}
j

Joffrey

10/19/2021, 11:52 PM
Kotlin has flow-sensitive typing, so it can smart cast the
student
variable to a more precise type (
Student
) after the
as
cast even without using a separate variable (simply because it knows the cast would have failed otherwise). It's the same principle as null checks that smart cast to non-null type inside the
if
.
b

blue

10/19/2021, 11:56 PM
I’d imagine it will work if I add the below statement instead of the
student as Student
. But it is not working
assert(student is Student)
j

Joffrey

10/20/2021, 12:01 AM
I guess
assert
doesn't have a contract, or maybe not one that's precise enough to help the compiler here (EDIT: this is actually because
assert
uses JVM assertions, which can be disabled). OTOH, the cast with
as
operator is pretty obvious to the compiler, and it's reliable.
Note that
require(student is Student)
does have a contract that allows this to compile - and it's multiplatform
👍 1
:thank-you: 1
b

blue

10/20/2021, 12:10 AM
Even
check(student is Student)
is working
j

Joffrey

10/20/2021, 12:14 AM
Yes, that works too. But keep in mind that they don't have the same semantics.
check
and
require
don't throw the same exception (
IllegalStateException
vs
IllegalArgumentException
respectively). You should use
require
if it's input that needs to be checked, and
check
if you want to verify that some state matches your expectations at some point (e.g. initialization has happened before usage, things like that).