https://kotlinlang.org logo
#getting-started
Title
# getting-started
r

Ray Rahke

02/21/2024, 6:42 PM
you mean internally?
🧵 6
s

Shawn

02/21/2024, 6:43 PM
wherever it makes the most sense
Copy code
components.asSequence()
    .filterIsInstance<SubA>()
    .first()
(assuming you want the component list evaluated lazily)
r

Ray Rahke

02/21/2024, 6:44 PM
i am not sure how to o that insie of the method
Untitled.kt
like this?
s

Shawn

02/21/2024, 6:45 PM
you would need to make
findFirstInstance()
an
inline fun
and make the type parameter
reified T : Base
r

Ray Rahke

02/21/2024, 6:45 PM
will that work if I need to overload this function
later
s

Shawn

02/21/2024, 6:46 PM
it depends on what you're gonna overload the function with
r

Ray Rahke

02/21/2024, 6:47 PM
first signature returns a T
second returns a T[]
based on if the component you look for is stackable
you cant have multiple rigidbodies
s

Shawn

02/21/2024, 6:47 PM
that just sounds like you want a different method name
r

Ray Rahke

02/21/2024, 6:47 PM
nah I want to be able to have get(RigidBody::class) -> a single result get(SpellEffect::class) -> list result
the logic to determine is like if ComponentType is Stackable
with Stackable being a marker interface i define
s

Shawn

02/21/2024, 6:49 PM
why would a method named
findFirstInstance
return multiple instances lol
r

Ray Rahke

02/21/2024, 6:49 PM
yeah lol sorry I had done that for the toy example on this server
its real name is just get
s

Shawn

02/21/2024, 6:49 PM
I still don't think that's especially ergonomic
r

Ray Rahke

02/21/2024, 6:50 PM
users of the game engine will specify whether their custom component conceptually should be stackable
like a spell effect, you expect to be able to have multiple at once
but not multiple 3DPositions
so they already define that
class SpellEffect : Stackable
using interface inheritance
it seems like a waste to not use that
having getSingleComponent() and getAllComponent()
seems worse than just having 1 get(Component), and having our codebase be intelligent enough to know whether or not the result will be a list
cause you already said so with Stackable
s

Shawn

02/21/2024, 6:51 PM
being implicit isn't necessarily more intelligent but w/e it's not my API
r

Ray Rahke

02/21/2024, 6:53 PM
yeah but i would think "everyone in my codebase already knows that 3DPosition is definitionally not stackable. why can't the get() function be smart enough to know that the result necessarily will only be 1 thigng?"
i do this pretty easily in typescript
s

Shawn

02/21/2024, 6:53 PM
well, it looks you can overload the method with different `KClass`s without worrying about erasure
r

Ray Rahke

02/21/2024, 6:54 PM
in unity c# you just have 1 get() function, but it always returns a list... So you end up doing 3dposition = Get<3DPosition>()[0]
that [0] is so gross
well, it looks you can overload the method with different `KClass`s without worrying about erasure
i actually dont think i need to overload at all
because this is just a runtime check
get(type: KClass<Base>) { if type is Stackable { return filterall else return filterfirst }
but the issue here is the return will just be seen as Base to the compiler
i need as T and as T[]
for each return
s

Shawn

02/21/2024, 6:56 PM
that won't exactly work, you would need
type == Stackable::class
because you're not working with a class instance
r

Ray Rahke

02/21/2024, 6:56 PM
right
thanks
s

Shawn

02/21/2024, 6:56 PM
but also, why not just use the overload?
r

Ray Rahke

02/21/2024, 6:56 PM
im not sure how the overload would work
oh let me see
i think ig ot it
@Shawn the overload still doesnt solve the
as
cat
cast
s

Shawn

02/21/2024, 7:00 PM
I mean, an unchecked cast is _probably_(?) going to be necessary no matter what unless you can get creative with the generics
how do you envision the method being used? like what do you want the callsite to look like?
r

Ray Rahke

02/21/2024, 7:03 PM
@Shawn an example use case would be like PhysicsSystem { apply() { position = entity.get(Position::class) forces = entity.get(PhysicalForce::class) for force in forces: position.move(force)
so sometimes get returns a single thing, sometimes an iterable array of things
Untitled.kt
i don't understand why this doesn't work...
is Kotlin compiler not intelligent enough to see that any code inside of an
if x is Blah
condition, then
x
definitely is
Blah
?
so the
as Blah
should be trivially trustworthy
oh sorry my code is wrong
1
i never make it be a single elemet
s

Shawn

02/21/2024, 7:06 PM
well also, you're returning
T
r

Ray Rahke

02/21/2024, 7:06 PM
return found.first() as T
s

Shawn

02/21/2024, 7:06 PM
that's another reason to overload
you can only return one type from a method lol
r

Ray Rahke

02/21/2024, 7:06 PM
oh right
yeah TS lets me say : T | T[]
K but how will kotlin infer which overload I am using
both functions just take in a class type...
and you always pass Component classes
Untitled
s

Shawn

02/21/2024, 7:08 PM
I think you'd need a
Stackable
and an
Unstackable
type (or named whatever you'd like) in order to differentiate
r

Ray Rahke

02/21/2024, 7:09 PM
yeah but Stackable is just an interface
technically it has no link to the Component base class
you could make anything Stackable.
is there a way for me to say that an interface can only be extended by certain children
s

Shawn

02/21/2024, 7:10 PM
you can prevent consumers from extending an interface by making it
sealed
r

Ray Rahke

02/21/2024, 7:10 PM
consumers need to be able to extend an interface with their custom component classes
class MyCustomComponent : Component(), Stackable
but this should only make sense if its a component
not some random class
I guess I could do class inheritance and have a hierarchy of two classes
that works
but still the as T is a problem
Untitled.kt
Cannot check for instance of erased type: T
how is this erased?
s

Shawn

02/21/2024, 7:17 PM
generics are erased on the JVM after compilation
r

Ray Rahke

02/21/2024, 7:18 PM
then this ??
Untitled.kt
feel like this is just beyond the ability of kotlin type analysis
is there a way I can just force the casting
without a warning
wait does
as
do a literal runtime cast?
i don't need that. it already is that type guaranteed
I just need the language server to know that it is
think the overload just avoids this actually.
s

Shawn

02/21/2024, 7:26 PM
It depends on how you write the methods—if you use
reified
, you can smart-cast but you can't use the same name (the overload will be ambiguous and won't resolve). if you accept two different
KClass
types, you will have to manually cast but you can use the same name