is there a way to accomplish this without finding ...
# getting-started
h
is there a way to accomplish this without finding some class from which both inherit?
s
overloading and delegation to a private method that holds common logic is probably the general solution
h
could you perhaps give me an example? delegation is something i'm not super comfortable with, and i'm not sure what we'd be overloading here
a specific example of what i'd like to accomplish:
Copy code
class SynchedPairs<K, V> {
    val a = ArrayList<Pair<K, V>>()
    val b = ArrayList<Pair<V, K>>()

    operator fun get(key: K): V = a[key]
    operator fun get(key: V): K = b[key]
}
but that doesn't work, because they share signatures
so i tried doing it inline with reified types, but that means the return type will be Any?, meaning it would require explicit typing when you call the function, eliminating much of the convenience i want to create here.
make sense?
s
Well, my recommendation would work with concrete types, generics make things a bit more complex
h
yeah, it's just I like using generics as much as possible because it's good refactoring practice and I think it makes things more readable
s
in your case I don’t really know what you’d really be able to do aside from define non-operator functions like
getK
and
getV
h
yeah and that's really unfortunate
s
maybe
@JvmName
would help here, but that’s maybe a bit of a stretch
h
shame kotlin doesn't smartcast the output of inline functions
to the precise type that the function returns in this case
...or...does it?
s
I don’t think inlining should change the behavior of smartcasting
buuuut I just tried out the
@JvmName
solution and it doesn’t give me compile errors
h
yeah, i get you, but do you agree it would be nice to accomplish what i'm trying to?
s
Copy code
class Test<K, V> {
  val a = mutableMapOf<K, V>()
  val b = mutableMapOf<V, K>()

  @JvmName("getK")
  operator fun get(key: K): V? = a[key]

  @JvmName("getV")
  operator fun get(key: V): K? = b[key]
}
h
how does this help me?
or rather
s
From Kotlin you’ll be able to define your operator `get`s and use them without having to call specific methods
h
would i still call it as a standard get operator?
s
yep
you’d just need to use those
getX
methods from Java
h
I'm kind of baffled the solution was... like this
ah, i get it
s
The problem with even inlined methods is that the method still needs to be generated and named at compile time before it gets inlined into a method body
so those methods still need to be distinct to the JVM
h
I feel like i'll be using this annotation... quite a bit...
i really should probably use more of them, but i don't fully understand what they are. i think from context they are directions to the compiler.
the only other one i've used in kotlin was
@JvmStatic
because...well, obviously
s
Some annotations are, other annotations are directives or metadata for other frameworks like Guice which handles dependency injection
h
yeah, in angular they are like constructor arguments
s
the
@Jvm*
ones are provided by the language to ease JVM interop problems
for your particular case, I feel like you’re more just brushing up against the limits of the Kotlin type system and generics on the JVM
h
Is JB trying to bake it into the kotlin compiler to deprecate those annotations?
s
I mean, the annotations are supposed to be used judiciously, to ease the occasional conflict
afaik JB probably isn’t planning on prioritizing more of the math-ey type system features
h
hmm
s
TypeScript and Elm and F# are all tackling that kind of thing, and it likely just appeals to their userbases more than Kotlin’s
h
TypeScript is the only other language that really competes as my favorite to write in. There are times, however, i really just wish I had pointers, and pass by value / reference
i wish i liked writing in cpp more
s
Personally speaking I’m pretty glad I don’t have to manage things like pointers and move/copy semantics
h
i prefer that i don't have also; just like with garbage collection, but it would be nice to have the option somehow
p
Interesting which method will be called in example with
@JvmName
if
K
and
V
will be the same type 🙂
h
hmmm, that's a good point
s
Pretty sure the class will just be unusable at that point
h
i could certainly make it unusable
s
you’ll just get an overload resolution ambiguity error at compile time
h
Copy code
class BidirectionalMap<K, V> {
    val a = mutableMapOf<K, V>()
    val b = mutableMapOf<V, K>()

    operator fun get(key: K): V? = a[key]

    @JvmName("getB")
    operator fun get(key: V): K? = b[key]

    operator fun set(key: K, value: V) {
        a[key] = value
        b[value] = key
    }

    @JvmName("setB")
    operator fun set(key: V, value: K) {
        b[key] = value
        a[value] = key
    }

    operator fun contains(key: K): Boolean = a.containsKey(key)

    @JvmName("containsB")
    operator fun contains(key: V): Boolean = b.containsKey(key)
}
we'll see how this works
if it does, i can expand it to have sort and other shit