you mean internally?
# getting-started
r
you mean internally?
🧵 6
s
wherever it makes the most sense
Copy code
components.asSequence()
    .filterIsInstance<SubA>()
    .first()
(assuming you want the component list evaluated lazily)
r
i am not sure how to o that insie of the method
Untitled.kt
like this?
s
you would need to make
findFirstInstance()
an
inline fun
and make the type parameter
reified T : Base
r
will that work if I need to overload this function
later
s
it depends on what you're gonna overload the function with
r
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
that just sounds like you want a different method name
r
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
why would a method named
findFirstInstance
return multiple instances lol
r
yeah lol sorry I had done that for the toy example on this server
its real name is just get
s
I still don't think that's especially ergonomic
r
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
being implicit isn't necessarily more intelligent but w/e it's not my API
r
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
well, it looks you can overload the method with different `KClass`s without worrying about erasure
r
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
that won't exactly work, you would need
type == Stackable::class
because you're not working with a class instance
r
right
thanks
s
but also, why not just use the overload?
r
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
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
@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
well also, you're returning
T
r
return found.first() as T
s
that's another reason to overload
you can only return one type from a method lol
r
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
I think you'd need a
Stackable
and an
Unstackable
type (or named whatever you'd like) in order to differentiate
r
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
you can prevent consumers from extending an interface by making it
sealed
r
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
generics are erased on the JVM after compilation
r
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
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