https://kotlinlang.org logo
Title
t

twisterrob

08/14/2018, 7:58 PM
what's the syntax for checking type and then using typed object? kind of like a
.let<Type> { }
val something: X
fun f() {
	if (something is Y) {
		(something as Y).g()
	}
}
I see two options:
val something: X
fun f() {
	val cacheOfSomething = something
	if (cacheOfSomething is Y) {
		(cacheOfSomething as Y).g()
	}
}
or
(something as? Y)?.g()
neither of which is pleasing, any other way to do this?
a

adam-mcneilly

08/14/2018, 7:59 PM
If you have
(something is Y)
you should be able to smartcast inside of that block, no?
👆 3
d

dknapp

08/14/2018, 7:59 PM
you don't need to cast it with as if you are in the scope of the if x is y check
a

adam-mcneilly

08/14/2018, 7:59 PM
if (thing is String) { println(thing.length) }
2
t

twisterrob

08/14/2018, 8:34 PM
oh, sorry, the val is outside the scope of the funciton, it could change value over time (custom getter) the
as Y
is not showing as redundant
a

adam-mcneilly

08/14/2018, 8:35 PM
ooo
Well sometimes I'll do
(something as? MyClass)?.let { ... }
which would work in your example I believe
t

trevjones

08/14/2018, 9:35 PM
something.takeIf { it is Y }?.let { it.g() }
😬 1
a

adam-mcneilly

08/14/2018, 9:36 PM
Robert, what about
(something as? Y)?.g()
wasn't preferable to you? I think it's the most idiomatic way to accomplish what you're trying to do.
t

trevjones

08/14/2018, 9:42 PM
or i guess drop the let block.
something.takeIf { it is Y }?.g()
one bonus of using
is
is that the ide can tell you the check for instance is always true/false.
t

twisterrob

08/14/2018, 10:14 PM
@trevjones I like
takeIf
, but I'm trying to call
Y.g()
, not
X.g()
😞 (
takeIf
is not aware of cast) @adam-mcneilly it introduces null to the mix, even though there's nothing nullable going on in the expression, it's just a simple non-null typecheck+cast.
t

trevjones

08/14/2018, 10:18 PM
perhaps this:
inline fun <reified T, R: Any> Any?.takeAs(crossinline block: (T) -> R?): R? {
  return if (T::class.java.isInstance(this)) block(this as T) else null
}
something.takeAs<Y> { it.g() }
t

twisterrob

08/14/2018, 10:24 PM
yep, just got to a similar conclusion:
inline fun <reified T> Any.run(crossinline block: T.() -> Unit) {
	if (this is T) { block(this) }
}
note: you can do
this is T
on reified no need for explicit reflection.
t

trevjones

08/14/2018, 10:25 PM
yea I just like the
isInstance
because I can hit F1 on it and get a spew of documentation
🤔 1