Question: is there a way to mark an interface as "...
# getting-started
k
Question: is there a way to mark an interface as "can only be implemented by a certain type and its subclasses"? Better yet, is there an alternate way to express the intent? I'm trying to wrap my hands around something like:
Copy code
interface Extender<T> {
  context(thisValue: T)
  fun doSomething()
}

class Foo : Extender<Foo> {
  context(thisValue: Foo)
  override fun doSomething() { ... }
  
  // So, Foo would need a context-free overload of doSomething() anyways
  // passing itself as context, in order for outsiders to use it?
  fun doSomething() = context(this) { doSomething() }
}
j
sealed
! I'll get you an example.
Though, I'm a little confused by your example. Context would probably help
Copy code
sealed interface CanOnlyBeImplementedInThisFile {}
open class CanBeSubclassed: CanOnlyBeImplementedInThisFile
k
sealed
wouldn't work in my use case, necessarily. For an academic example, consider this:
Copy code
interface InfixOp<T> {
  infix fun op(rhs: T): T
}

interface InfixOpTrait<T> {
  fun op(lhs: T, rhs: T): T
}

class MyType : InfixOp<MyType> {
  object InfixTrait : InfixOpTrait<T> { ... }
  
  override fun op(rhs: T) = InfixTrait.op(lhs, rhs)
}
The intent is to make
InfixOp
implementable only by
T
, so that you can have a "this value" available with a default implementation of
InfixOp.op
, in the hope that some boilerplate could be removed. Something like
Copy code
interface InfixOp2<T> {
  context(thisVal: T)
  infix fun op(rhs: T): T
}
j
I think I see - you're trying to jank your way into a 'self' type kind of thing? This isn't real Kotlin, but expresses what you're actually trying to do roughly?
Copy code
interface InfixOp { infix fun op(rhs: Self): Self }
n
If I'm understanding correctly, couldn't you just have an extension function on a generic type with a bound?
Copy code
fun <T : CharSequence> T.op() = TODO()
k
It could be an interface with multiple functions, and I'm not sure how you can implement an interface using only extensions.
Copy code
interface InfixOp3<T> {
  infix fun T.op(rhs: T): T
}
That doesn't look like it does what I think it does.
n
No, I don't think it would in practice. The example provided only really works for a single function, not if you want multiple function, or more "ad-hoc" trait implementations on types like in Rust.
j
Still confused as to what you're going for @Kelvin Chung. Is it the self-typing thing I wrote above, kind of like how
Comparable<T>
would ideally work?
k
Kind of a self typing thing, yes.
Similar to "implement
Comparable
backed by a `Comparator`" in that sense.
j
All right. Yeah, I don't think there's anything you can really use for this. `Comparable<T>`'s lack of something like this is a good hint that the designers of Kotlin don't have an intended answer.
k
Yeah, I was hoping for something like
Copy code
interface ContextedComparable<T> {
  context(thisVal: T, cmp: Comparator<T>)
  fun compareTo(rhs: T): Int = cmp.compare(thisVal, rhs)
}
But that just creates more boilerplate, now that I think about it. I think that a context-free
Comparable
backed by a
Comparator
may be crossing a line somewhere, but a context-sensitive one (which might be useful for wrapper value classes) wouldn't require that many hoops.