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

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.

Related

Allow function calls only in special context

I'm trying to write a class that only allows certain methods to be called in a lambda of one function.
Basically, I want to achieve similar behaviour to how you can only call suspend functions in a suspend context.
Right now the closest I can get is this.
class MyClass {
fun runCommands(block: CommandContext.() -> Unit) {
// do prep work
block.invoke(commandContext)
// do cleanup work
}
val commandContext = CommandContext()
inner class CommandContext {
fun commandFunc() {} // only callable from the lambda
}
}
The issues I'm having with this is I can't make CommandContext private so you could always make your own instance and run the command externally. It is also unnecessary for it to be instantiatable but I can't make an "inner object."
Any ideas on how to do this cleaner?
Outer scope should know that there is a commandFunc() method in CommandContext class (and that this class actually exists). That's why it can't be private. But you can encapsulate its implementation, effectively making it private, keeping public only its interface:
interface CommandContext {
fun commandFunc()
}
class MyClass {
fun runCommands(block: CommandContext.() -> Unit) {
// do prep work
block.invoke(CommandContextImpl)
// do cleanup work
}
private object CommandContextImpl : CommandContext {
override fun commandFunc() {} //actual implementation
}
}
//Usage:
fun main() {
MyClass().runCommands { commandFunc() }
}

Is there a way to verify that a top-level function passed as a dependency to a class has been called during testing?

I have a class that receives a function allowing it to display things on the UI during a failure case. What's the best way that I can verify that the function is called in my test?
MyClass(private val uiPrinter: (String) -> Unit) {
fun foo() {
// do some stuff
uiPrinter("printing from foo!")
// do some more stuff
}
}
MyClassTest() {
val testUiPrinter: (String) -> Unit = { System.out.println(it) }
#Test
fun uiPrinterIsInvoked() {
val myClass = MyClass(testUiPrinter)
myClass.foo()
// can I verify that testUiPrinter has been invoked?
}
}
You may want to check out the Model-View-Presenter architecture. Its purpose is to hide the Android framework behind an abstract View interface which a purely Java Presenter can interact with. In your example:
interface ViewInterface {
fun printError(error: String)
}
class MyPresenter(private val view: ViewInterface) {
fun foo() {
// do some stuff (testable stuff)
view.printError("Printing from foo()!")
// do some more (testable) stuff
}
}
class MyPresenterTest() { // Test using Mockito to mock the abstract view
private val view = mock(ViewInterface::class.java)
private val presenter = MyPresenter(view)
#Test
fun printsError() {
// set up preconditions
presenter.foo()
verify(view).printError("Printing from foo()!")
}
}
Your concrete view will generally be an Android Activity, Fragment, or View which implements the view interface. Notice MyPresenter only expects the abstract view and does not need knowledge of the framework-dependent operations.
class MyActivity : Activity(), ViewInterface {
// ...
override fun printError(error: String) {
textView.text = error // For example
}
// ...
}
This can be achieved by mocking the higher-order function as higher-order functions are objects unless inlined.
#Mock
val testUiPrinter: (String) -> Unit
#Test
fun uiPrinterIsInvoked() {
val myClass = MyClass(testUiPrinter)
myClass.foo()
verify(testUiPrinter).invoke("Printing from foo!")
}

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 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
*/

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()