Can kotlin interface detects, on which class is attached to, on its own? - kotlin

I have generic interface...
interface Parent<T> {
fun function(entity: T): Int
}
And when I implement functionality with some child class...
class Other : Parent<Other> {
override fun function(entity: Other): Int {
return 42
}
}
I'm bothered with the fact that I have to pass the same class type while implementing the interface... I would really like for the interface to be able to detect on which class is attached on its own without me providing the same type again...
I would like code something like this...
class Other : Parent {
override fun function(entity: Other): Int {
return 42
}
}
Is it possible in kotlin to do that in some form?

Not in the general case, but sometimes when a generic is fully constrained by another: https://kotlinlang.org/docs/generics.html#underscore-operator-for-type-arguments

Related

Serializer for sealed interface (kotlinx.serialization)

I am trying to serialize my base class that is implementing two sealed interfaces. I have tried multiple approaches, yet i always get the error :
caused by: kotlinx.serialization.SerializationException: Class 'PayloadFromBuilder' is not registered for polymorphic serialization in the scope of 'Payload'.
Mark the base class as 'sealed' or register the serializer explicitly.
I was following mostly this guide Kotlinx/polymorphism and checked some similar questions here.
My code:
sealed inteface MyClass {
dataetc
}
#Serializable
private class DefaultMyClass(dataetc): MyClass
fun MyClass(dataetc): MyClass = DefaultMyClass
Sealed interface MyClassBuilder {
fun dataetc(value: ByteArray)
fun dataetc(value: ByteArray)
fun dataetc(value: ByteArray?)
}
#PublishedApi
#Serializable
#SerialName("payload")
internal class MyClassFromBuilder: MyClassBuilder, MyClass {
}
//Serialization
val module = SerializersModule {
polymorphic(MyClass::class) {
subclass(MyClassFromBuilder::class, MyClassFromBuilder.serializer())
default { MyClassFromBuilder.serializer() }
}
polymorphic(MyClassBuilder::class) {
subclass(MyClassFromBuilder::class, MyClassFromBuilder.serializer())
default { MyClassFromBuilder.serializer() }
}
}
val ConfiguredProtoBuf = ProtoBuf { serializersModule = module }
#ExperimentalSerializationApi
internal inline fun <reified T> ProtoBuf.encodeToMessage(value: T): Message =
Message(encodeToByteArray(value))
From what i have seen i think i am very close to the solution yet i am missing something, since my example is very generic if you need more info let me know, thank you in advance.
Note: In my several tries i have tried to annotate both sealed intefaces with #Polymorphic but i am not sure if it changed anything.
Note 2: My code breaks when i am calling the encodeToMessage fun
So i messed big time, turns out i was not using my ConfiguredProtoBuf when i was calling my encodeToMessage

Refer to own type in Kotlin object member

I have some objects like so:
interface Maker<T : Thing>
interface Thing
I want Thing to hold a reference to its Maker, but I can't figure out how:
interface Thing {
val maker: Maker<this::class> // ??
}
so that I can have something like:
class BallMaker : Maker<Ball>
object Ball : Thing {
override val maker = BallMaker
}
How can I achieve this?
From the perspective of Thing, its maker must be defined as simply Maker<*>, meaning any kind of maker at all.
You could parameterize Thing with the subclass.
interface Maker<T : Thing<T>> {
}
interface Thing<T : Thing<T>> {
val maker: Maker<T>
}
class Ball : Thing<Ball> {
override val maker: Maker<Ball>
}
If you define your Maker interface like so:
interface Maker<out T : Thing>
fun make(): T
}
Then your Thing interface can be defined as:
interface Thing {
val maker: Maker<Thing>
}
Due to the use of out, implementations can be defined as:
class BallMaker : Maker<Ball> {
override fun make(): Ball = TODO("not implemented")
}
class Ball : Thing {
override val maker = BallMaker()
}
Here, the maker property will be of type BallMaker. You could also use:
override val maker: Maker<Ball> = BallMaker()
If you would rather expose the interface type instead of the implementation.
See Generics: in, out, where - Kotlin Programming Language for more information on generics in Kotlin. An important thing to know about using out is that:
The general rule is: when a type parameter T of a class C is declared out, it may occur only in out-position in the members of C, but in return C<Base> can safely be a supertype of C<Derived>.
In other words, if a generic parameter is defined with out it can only be used as return types, not parameter types. The opposite is true of in.
Of course, if your Maker interface only has one method you may want to consider using a function type instead.
interface Thing {
val maker: () -> Thing
}
This will still allow you to do:
class Ball : Thing {
// type can be inferred to "() -> Ball" instead in this case
override val maker: () -> Ball = { Ball() }
}
If you want to name the function type, use a type alias.

Static Instance of Interface as part of the interface

Imagine I had an interface like:
interface MyInterface {
fun doSomething()
}
And I was interop-ing between Kotlin and Java. I now want a constant static instance of this interface but I want that to be part of the interface. I could do this:
interface MyInterface {
fun doSomething()
companion object {
val CONSTANT = object: MyInterface {
override fun doSomething() { ... }
}
}
}
but that means I need to write MyInterface.Companion.getCONSTANT(). #JvmField doesn't work here.
I've also tried:
interface MyInterface {
fun doSomething()
object CONSTANT: MyInterface {
override fun doSomething() { ... }
}
}
}
Which works in other Kotlin files (I can write MyInterface.CONSTANT) but I'd have to write MyInterface.CONSTANT.INSTANCE in Java. This solution seems the closest to what I want.
Any solutions? I want to be able to write MyInterface.CONSTANT in both Kotlin and Java and have them refer to a single static final object that implements the interface.
I believe I could also convert my Interface to an abstract class but that's the last resort.
The issue of not being able to use #JvmStatic in interfaces is tracked in this ticket: https://youtrack.jetbrains.com/oauth?state=%2Fissue%2FKT-6301
It is fixed by now and one comment says
Fix would be avaliable in 1.2.30 under '-language-version 1.3' option

Method References to Super Class Method

How to use method references to refer to super class methods?
In Java 8 you can do SubClass.super::method.
What would be the syntax in Kotlin?
Looking forward to your response!
Conclusion
Thanks to Bernard Rocha!
The syntax is SubClass::method.
But be careful. In my case the subclass was a generic class. Don't forget to declare it as those:
MySubMap<K, V>::method.
EDIT
It still doesn't work in Kotlin.
Hers's an example in Java 8 of a method reference to a super class method:
public abstract class SuperClass {
void method() {
System.out.println("superclass method()");
}
}
public class SubClass extends SuperClass {
#Override
void method() {
Runnable superMethodL = () -> super.method();
Runnable superMethodMR = SubClass.super::method;
}
}
I'm still not able to do the same in Kotlin...
EDIT
This is an example how I tried to achieve it in Kotlin:
open class Bar {
open fun getString(): String = "Hello"
}
class Foo : Bar() {
fun testFunction(action: () -> String): String = action()
override fun getString(): String {
//this will throw an StackOverflow error, since it will continuously call 'Foo.getString()'
return testFunction(this::getString)
}
}
I want to have something like that:
...
override fun getString(): String {
//this should call 'Bar.getString' only once. No StackOverflow error should happen.
return testFunction(super::getString)
}
...
Conclusion
It's not possible to do so in Kotlin yet.
I submitted a feature report. It can be found here: KT-21103 Method Reference to Super Class Method
As the documentation says you use it like in java:
If we need to use a member of a class, or an extension function, it
needs to be qualified. e.g. String::toCharArray gives us an extension
function for type String: String.() -> CharArray.
EDIT
I think you can achieve what you want doing something like this:
open class SuperClass {
companion object {
fun getMyString(): String {
return "Hello"
}
}
}
class SubClass : SuperClass() {
fun getMyAwesomeString(): String {
val reference = SuperClass.Companion
return testFunction(reference::getMyString)
}
private fun testFunction(s: KFunction0<String>): String {
return s.invoke()
}
}
Don't know if it is possible to get the reference to super class's function, but here is an alternative to what you want to achieve:
override fun getString(): String = testFunction { super.getString() }
According to Bernardo's answer, you might have something like this. It doesn't have remarkable changes.
fun methodInActivity() {
runOnUiThread(this::config)
}
fun config(){
}
What is more, in the incoming 1.2 version you can use just
::config

How to specify "own type" as return type in Kotlin

Is there a way to specify the return type of a function to be the type of the called object?
e.g.
trait Foo {
fun bar(): <??> /* what to put here? */ {
return this
}
}
class FooClassA : Foo {
fun a() {}
}
class FooClassB : Foo {
fun b() {}
}
// this is the desired effect:
val a = FooClassA().bar() // should be of type FooClassA
a.a() // so this would work
val b = FooClassB().bar() // should be of type FooClassB
b.b() // so this would work
In effect, this would be roughly equivalent to instancetype in Objective-C or Self in Swift.
There's no language feature supporting this, but you can always use recursive generics (which is the pattern many libraries use):
// Define a recursive generic parameter Me
trait Foo<Me: Foo<Me>> {
fun bar(): Me {
// Here we have to cast, because the compiler does not know that Me is the same as this class
return this as Me
}
}
// In subclasses, pass itself to the superclass as an argument:
class FooClassA : Foo<FooClassA> {
fun a() {}
}
class FooClassB : Foo<FooClassB> {
fun b() {}
}
You can return something's own type with extension functions.
interface ExampleInterface
// Everything that implements ExampleInterface will have this method.
fun <T : ExampleInterface> T.doSomething(): T {
return this
}
class ClassA : ExampleInterface {
fun classASpecificMethod() {}
}
class ClassB : ExampleInterface {
fun classBSpecificMethod() {}
}
fun example() {
// doSomething() returns ClassA!
ClassA().doSomething().classASpecificMethod()
// doSomething() returns ClassB!
ClassB().doSomething().classBSpecificMethod()
}
You can use an extension method to achieve the "returns same type" effect. Here's a quick example that shows a base type with multiple type parameters and an extension method that takes a function which operates on an instance of said type:
public abstract class BuilderBase<A, B> {}
public fun <B : BuilderBase<*, *>> B.doIt(): B {
// Do something
return this
}
public class MyBuilder : BuilderBase<Int,String>() {}
public fun demo() {
val b : MyBuilder = MyBuilder().doIt()
}
Since extension methods are resolved statically (at least as of M12), you may need to have the extension delegate the actual implementation to its this should you need type-specific behaviors.
Recursive Type Bound
The pattern you have shown in the question is known as recursive type bound in the JVM world. A recursive type is one that includes a function that uses that type itself as a type for its parameter or its return value. In your example, you are using the same type for the return value by saying return this.
Example
Let's understand this with a simple and real example. We'll replace trait from your example with interface because trait is now deprecated in Kotlin. In this example, the interface VitaminSource returns different implementations of the sources of different vitamins.
In the following interface, you can see that its type parameter has itself as an upper bound. This is why it's known as recursive type bound:
VitaminSource.kt
interface VitaminSource<T: VitaminSource<T>> {
fun getSource(): T {
#Suppress("UNCHECKED_CAST")
return this as T
}
}
We suppress the UNCHECKED_CAST warning because the compiler can't possibly know whether we passed the same class name as a type argument.
Then we extend the interface with concrete implementations:
Carrot.kt
class Carrot : VitaminSource<Carrot> {
fun getVitaminA() = println("Vitamin A")
}
Banana.kt
class Banana : VitaminSource<Banana> {
fun getVitaminB() = println("Vitamin B")
}
While extending the classes, you must make sure to pass the same class to the interface otherwise you'll get ClassCastException at runtime:
class Banana : VitaminSource<Banana> // OK
class Banana : VitaminSource<Carrot> // No compiler error but exception at runtime
Test.kt
fun main() {
val carrot = Carrot().getSource()
carrot.getVitaminA()
val banana = Banana().getSource()
banana.getVitaminB()
}
That's it! Hope that helps.
Depending on the exact use case, scope functions can be a good alternative. For the builder pattern apply seems to be most useful because the context object is this and the result of the scope function is this as well.
Consider this example for a builder of List with a specialized builder subclass:
open class ListBuilder<E> {
// Return type does not matter, could also use Unit and not return anything
// But might be good to avoid that to not force users to use scope functions
fun add(element: E): ListBuilder<E> {
...
return this
}
fun buildList(): List<E> {
...
}
}
class EnhancedListBuilder<E>: ListBuilder<E>() {
fun addTwice(element: E): EnhancedListBuilder<E> {
addNTimes(element, 2)
return this
}
fun addNTimes(element: E, times: Int): EnhancedListBuilder<E> {
repeat(times) {
add(element)
}
return this
}
}
// Usage of builder:
val list = EnhancedListBuilder<String>().apply {
add("a") // Note: This would return only ListBuilder
addTwice("b")
addNTimes("c", 3)
}.buildList()
However, this only works if all methods have this as result. If one of the methods actually creates a new instance, then that instance would be discarded.
This is based on this answer to a similar question.
You can do it also via extension functions.
class Foo
fun <T: Foo>T.someFun(): T {
return this
}
Foo().someFun().someFun()