Inheriting multiple Interfaces and implementing methods with similar names at the same time - Kotlin - kotlin

I have the following code -
package multipleInterfaceDemo
fun main() {
println(MyClass(val1 = 1, val2 = 2).myFun())
}
private class MyClass(override val val1: Int, override val val2: Int): MyInterface1, MyInterface2 {
/*override fun myFun() {
super<MyInterface1>.myFun()
}*/
override fun myFun() {
super<MyInterface2>.myFun()
}
}
private interface MyInterface1 {
val val1: Int
public fun myFun() {
println(val1)
}
}
private interface MyInterface2 {
val val2: Int
public fun myFun() {
println(val2)
}
}
Here I have two private Interfaces - MyInterface1 and MyInterface2
Each interface has an Int type variable - val1 and val2 respectively which are set through constructors in implementing Class
Both my Interfaces have a method called myFun() which prints out val1 and val2 respectively.
Now I have a class MyClass that implements MyInterface1 and MyInterface2.
The Class has two constructor parameters for setting the variable values in the two interfaces implemented by the Class
Now both the Interfaces have a method having similar name - myFun() So there is ambiguity regarding method of which Interface is being implemented by overriding.
Here I clear the ambiguity by calling super method myFun() by using super keyword and after super placing angular brackets and within the brackets mentioning the super Interface type - MyInterface1 or MyInterface2
Now the problem which arises here is that I can override either the myFun() method of Interface1 or of Interface2. But I can't call the myFun() method of both the Interfaces at the same time.
So is it possible to do any code tweak so that I can call myFun() method of both Interface1 and Interface2 at the same time?
A similar C# question already exists -
Inheritance from multiple interfaces with the same method name
But I am unable to implement the answers in Kotlin

Not quite sure that this is what you need, but you can use both super<MyInterface1>.myFun() and super<MyInterface2>.myFun() in the same myFun function
private class MyClass(override val val1: Int, override val val2: Int): MyInterface1, MyInterface2 {
override fun myFun() {
super<MyInterface1>.myFun()
super<MyInterface2>.myFun()
}
}

Answer provided by IR42 is good but the following approach suits me better -
class MyClass() {
class MyInnerClass1(override val val1: Int): MyInterface1 {
override fun myFun() {
super<MyInterface1>.myFun()
}
}
class MyInnerClass2(override val val2: Int): MyInterface2 {
override fun myFun() {
super<MyInterface2>.myFun()
}
}
}
Main function from where the two methods are called at the same time -
fun main() {
println(MyClass.MyInnerClass1(val1 = 1).myFun())
println(MyClass.MyInnerClass2(val2 = 2).myFun())
}

Related

Kotlin: use generic on interface level as argument type for function

Is it impossible to use generic on interface level as argument type for function?
I read about out and in keywords but as I understand they don't work for this case.
interface BaseB
open class ChildB1: BaseB
open class ChildB2: BaseB
abstract class BaseMapper<V: BaseB> {
open fun test(v: V) {
return
}
}
class TestMapper1: BaseMapper<ChildB1>() {
override fun test(v: ChildB1) {
return
}
}
class TestMapper2: BaseMapper<ChildB2>() {
override fun test(v: ChildB2) {
return
}
}
#Test
fun t() {
//ERROR
val mappers: List<BaseMapper<BaseB>> = listOf(TestMapper1(), TestMapper2())
mappers[0].test(ChildB1())
}
A BaseMapper<ChildB1> is not logically a BaseMapper<BaseB>. It consumes ChildB’s, so if you passed some other implementation of Base it would cause a ClassCastException if the compiler let you do that. There is no common subtype of your two subclasses besides Nothing, so the only way to put both of these types in the same list is to make it a List<BaseMapper<in Nothing>>.
Example of why it is not logically a BaseMapper<BaseB>:
open class ChildB1: BaseB {
fun sayHello() = println("Hello world")
}
class TestMapper1: BaseMapper<ChildB1>() {
override fun test(v: ChildB1) {
v.sayHello() // if v is not a ChildB1, this would be impossible
}
}
//...
val impossibleCast: BaseMapper<BaseB> = TestMapper1()
// TestMapper1 cannot call sayHello() because it's undefined for ChildB2.
// This is impossible:
impossibleCast.test(ChildB2())
// ...so the compiler prevents you from doing the impossible cast in the first place.

This in kotlin interface delegation

Is there any way to pass this when using interface delegation? This would enable nice composability - but I found no way to do this.
Means something like:
interface Foo {
}
class FooImpl(bar: Bar) : Foo {
}
class Bar: Foo by FooImpl(this) {
}
as long as FooImpl doesnt need a parameter like this it works - but it would be great to access the other class there - perhaps someone knows a way. Otherwise I would also be interested if this is worth a KEEP if not - or if it will be impossible for some reason.
Delegation doesn't support this. The delegate has to be instantiated before the class that is delegating to it, so the delegate cannot rely on it for construction. Another gotcha is that although you can override functions of the delegate, if the delegate internally calls those functions, it calls the original version, not the override. The delegate really lives in its own world.
But you could set it up for the host to pass itself to the delegate in its initialization block:
interface Foo<T> {
var host: T
fun doSomething()
}
class FooImpl : Foo<Bar> {
override lateinit var host: Bar
override fun doSomething() {
println(host.name)
}
}
class Bar(val name: String): Foo<Bar> by FooImpl() {
init {
host = this
}
}
fun main() {
val bar = Bar("Hello world")
bar.doSomething()
}
This would unfortunately expose the host to the possibility of getting disconnected from its own delegate by outside classes, though. Maybe you could make the property throw an exception if assigned more than once.
Here's a property delegate that could do that:
private class SingleAssignmentVar<T>: ReadWriteProperty<Any, T> {
private var value: T? = null
private var assigned: Boolean = false
#Suppress("UNCHECKED_CAST")
override fun getValue(thisRef: Any, property: KProperty<*>): T {
if (!assigned)
error("Property has not yet been set.")
return value as T
}
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
if (assigned)
error("Property may only be set once.")
assigned = true
this.value = value
}
}
fun <T> Delegates.singleAssignment(): ReadWriteProperty<Any, T> = SingleAssignmentVar()
You may split your Bar class in two parts, say backend and frontend.
Frontend will be responsible for declaring interface with delegates, backend will host delegates and act as composition target.
For example:
interface Foo {
fun sayHello(): String
}
class FooImpl(val bar: BarBackend) : Foo {
override fun sayHello() = "Hello from ${bar.compositionTarget()}!"
}
class BarBackend() {
val fooImpl: FooImpl = FooImpl(this)
fun compositionTarget() = "backend"
}
class BarFrontend(backend: BarBackend) : Foo by backend.fooImpl
fun main() {
val bar = BarFrontend(BarBackend())
println(bar.sayHello())
}

Kotlin: platform declaration clash: same JVM signature

I'm trying to implement an abstract class in kotlin which extends a MultiValuedMap, when I was trying to override keySet() method, I got the error
platform declaration clash: The following declarations have the same JVM signature (keySet()Ljava/util/Set;)
My code:
abstract class ConfigProperties<K, V>(delegate: Map<K, V>?): MultivaluedMap<String, String> {
protected val delegate: Map<K, V>
init {
if (delegate == null) {
throw NullPointerException("Config properties delegate must not be null.")
}
this.delegate = delegate
}
abstract fun putCacheProperty(key: Parameter, value: Any)
abstract fun getCacheProperty(key: Parameter): Any
protected val UNSUPPORTED_MESSAGE = "ConfigProperties is immutable."
override fun keySet(): Set<String> {
return delegate.keys
}
}
Any hint to solve this? Thanks!
I think your problem begins with MultivaluedMap<String,String>
abstract class ConfigProperties<K, V>(delegate: Map<K, V>?):
MultivaluedMap<String, String> { ... }
Overlook the String type parameter for the moment. MultivaluedMap<K,V> is an interface that has the Map<K,List<V>> super interface. But in your code, you have a delegate of type Map<K,V>. You try to override a the setKey member of the Map<K,List<V>> super interface by returning delegate.keys which is not the same as Map<K,List<V>>.keys (i.e., whose member you are overriding).
So, you can try the following...
abstract class ConfigProperties<K, V>(delegate: Map<K, V>?):
MultivaluedMap<K, V> {
protected val delegate: Map<K, List<V>>
init {
if (delegate == null) {
throw NullPointerException("Config properties delegate must not be null.")
}
this.delegate = delegate
}
abstract fun putCacheProperty(key: Parameter, value: Any)
abstract fun getCacheProperty(key: Parameter): Any
protected val UNSUPPORTED_MESSAGE = "ConfigProperties is immutable."
override fun keySet(): Set<K> {
return delegate.keys
}
}
As for the String type parameter, did you mean to use K,V? Whatever you meant, you will need to make the consistent.

Kotlin: Can an abstract super class have an abstract constructor?

I have just written this, which is fine as far as it goes:
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.int
import com.github.salomonbrys.kotson.jsonObject
import com.google.gson.JsonElement
import com.google.gson.JsonObject
abstract class BatchJobPayload {
abstract fun toJson(): JsonObject
}
class BookingConfirmationMessagePayload(val bookingId: Int) : BatchJobPayload() {
constructor(payload: JsonElement) : this(payload["bookingId"].int)
override fun toJson() = jsonObject(
"bookingId" to bookingId
)
}
But I'd like to insist, if possible, that all classes that extend BatchJobPayload implement a secondary constructor with the signature
constructor(payload: JsonElement): BatchJobPayload, which is to be used for deserializing.
BookingConfirmationMessagePayload has such a constructor but only because I put it there, not because BatchJobPayload insisted upon it...
A workable option I came up with as as follows:
interface BatchJobPayload {
fun toJson(): JsonObject
}
interface BatchJobPayloadDeserialize {
operator fun invoke(payload: JsonElement): BatchJobPayload
}
class BookingConfirmationMessagePayload(val bookingId: Int) : BatchJobPayload {
override fun toJson() = jsonObject(
"bookingId" to bookingId
)
}
class BookingConfirmationMessagePayloadDeserialize : BatchJobPayloadDeserialize {
override operator fun invoke(payload: JsonElement) =
BookingConfirmationMessagePayload(payload["bookingId"].int)
}
Now you can deserialize a BookingConfirmationMessagePayload object from a JsonElement as follows:
BookingConfirmationMessagePayloadDeserialize()(payload)
(The invoke operator is just some syntactic sugar here which may border on the obtuse...)
Actually I still prefer the original code which is less verbose --- a developer needing to subclass BatchJobPayload in the future may initially neglect to define a constructor that takes a JsonElement but they will surely realise their omission once they have just a string of JSON which they need to turn into an instance of their new class...
You can't enforce a super constructor, but you can have factories with a spawn method enforced that returns a subclass of BatchJobPayload, which allows you to make sure classes will be constructable.
It would look something like this:
class JsonObject // Included to make compiler happy
abstract class Factory<T> {
abstract fun make(obj: JsonObject): T
}
abstract class Base {
abstract fun toJson(): JsonObject
}
class A(val data:JsonObject):Base() {
override fun toJson(): JsonObject {
return JsonObject()
}
}
class AFactory: Factory<A>() {
override fun make(obj: JsonObject): A {
return A(obj)
}
}
fun main(args: Array<String>) {
val dummyJson = JsonObject()
var factory = AFactory()
var instance = factory.make(dummyJson)
println(instance)
}

How kotlin delegation is useful?

I'm really confused about the kotlin delegation. Let me describe the regular polymorphism approach here which looks same like the kotlin delgation.
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
fun main(args: Array<String>) {
val b : Base = BaseImpl(10)
b.print() // prints 10
}
I can pass any implemented class of Base interface to b variable to call the method of specified class's object. Then what is the benefit of kotlin's delegation? Which is described here.
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b // why extra line of code?
// if the above example works fine without it.
fun main(args: Array<String>) {
val b = BaseImpl(10)
Derived(b).print() // prints 10
}
I know this is the simple scenario where the both codes are working fine. There should be a benefit of delegation that's why kotlin introduced it. What is the difference? and how kotlin delegation can be useful? Please give me a working example to compare with polymorphism approach.
Also remember that you're not restricted to just one delegate. Kotlin's way of implementing delegation is similar to traits implementation in languages like Groovy. You can compose different functionality via delegates. Kotlin's way can also be considered more powerful because you can "plug in" different implementations too.
interface Marks {
fun printMarks()
}
class StdMarks() : Marks {
override fun printMarks() { println("printed marks") }
}
class CsvMarks() : Marks {
override fun printMarks() { println("printed csv marks") }
}
interface Totals {
fun printTotals()
}
class StdTotals : Totals {
override fun printTotals() { println("calculated and printed totals") }
}
class CheatTotals : Totals {
override fun printTotals() { println("calculated and printed higher totals") }
}
class Student(val studentId: Int, marks: Marks, totals: Totals)
: Marks by marks, Totals by totals
fun main(args:Array<String>) {
val student = Student(1,StdMarks(), StdTotals())
student.printMarks()
student.printTotals()
val cheater = Student(1,CsvMarks(), CheatTotals())
cheater.printMarks()
cheater.printTotals()
}
Output:
printed marks
calculated and printed totals
printed csv marks
calculated and printed higher totals
You can't do this with inheritance.
It is extremely useful for creating decorators and for object composition.
Joshua Bloch in Effective Java, 2nd Edition, Item 16 'Favor Composition Over Inheritance' shows a good example: inheritance is easy-to-break, and decorators are not.
Inheritance:
class LoggingList<E> : ArrayList<E>() {
override fun add(e: E): Boolean {
println("added $e")
return super.add(e)
}
override fun addAll(e: Collection<E>): Boolean {
println("added all: $e")
return super.addAll(e) // oops! Calls [add] internally.
}
}
Delegation:
class LoggingList<E>(delegate: MutableList<E>) : MutableList<E> by delegate {
override fun add(e: E): Boolean {
println("added $e")
return delegate.add(e)
}
override fun addAll(e: Collection<E>): Boolean {
println("added all: $e")
return delegate.addAll(e) // all OK
// it calls [delegate]'s [add] internally, not ours
}
}
It is useful because of the Delegation Pattern where most of the behavior can be the same as the target of the delegation (b) but you just want to override a subset of methods to act differently.
An example would be an InputStream implementation which delegates all work to another InputStream but overrides the close() method to not close the underlying stream. This could be implemented as:
class CloseGuardInputStream(private val base: InputStream)
: InputStream by base {
override fun close() {}
}
Following is the example :-
interface Mode{
val color:String
fun display()
}
class DarkMode(override val color:String) : Mode{
override fun display(){
println("Dark Mode..."+color)
}
}
class LightMode(override val color:String) : Mode {
override fun display() {
println("Light Mode..."+color)
}
}
class MyCustomMode(val mode: Mode): Mode{
override val color:String = mode.color
override fun display() {
mode.display()
}
}
Now, the custom mode can reuse display() function of both modes DarkMode & LightMode
fun main() {
MyCustomMode(DarkMode("CUSTOM_DARK_GRAY")).display()
MyCustomMode(LightMode("CUSTOM_LIGHT_GRAY")).display()
}
/* output:
Dark Mode...CUSTOM_DARK_GRAY
Light Mode...CUSTOM_LIGHT_GRAY
*/
Kotlin natively support delegation pattern.
Kotlin provides by keyword to specify the delegate object which our custom mode will be delegating to.
We can achieve the same result of the code above using by keyword.
class MyCustomMode(val mode: Mode): Mode by mode
fun main() {
MyCustomMode(DarkMode("CUSTOM_DARK_GRAY")).display()
MyCustomMode(LightMode("CUSTOM_LIGHT_GRAY")).display()
}
/* output:
Dark Mode...CUSTOM_DARK_GRAY
Light Mode...CUSTOM_LIGHT_GRAY
*/