I'm not understanding this Kotlin example - kotlin

I'm learning Kotlin at school and it is beig quite difficult to me. I was given this example of code but I'm not understanding at all what it does, specially the part marked as a comment. I hope you can help me. Thanks
open class W{
open fun f(){
println("en W.f()")
}
}
class X : W(){
override fun f(){
println("en X.f")
}
// FROM HERE
inner class Y{
fun g() {
super#X.f()
f()
// UNTIL HERE
}
}
}
fun main() {
val x = X()
x.Y().g()
}

There's a class inside of X called Y. If you look in main, you are creating an X, and then creating a Y through the dot access, and then running the g that is a member of Y.

Related

Can sealed class subclasses call a inherited method and return the subclass instance?

How can I share sealed class methods by the subclasses and return the typeof "this"? I don't want to cast every time I call it, but implement it in the method signature if possible. Is there a simple way?
sealed class Base {
fun customCopy() = when (this) {
is X -> copy()
is Y -> copy()
}
}
data class X(val x: String) : Base()
data class Y(val y: String) : Base()
fun main() {
val x1 = X("x")
val x2: X = x1.customCopy() // Required X, but found Base
}
Above, I want x1.customCopy() to return X instead of Base.
You have to use generics to implement it.
Something like this:
fun <T: Base> customCopy():T = when (this) {
is X -> copy()
is Y -> copy()
} as T
Or you can use extension function which provides more type safety:
fun <T: Base> T.extCopy():T = when(this) {
is X -> copy()
is Y -> copy()
else -> throw InvalidParameterException()
} as T
That doesn't really make any sense, might be more clear for you if you add the explicit return type of customCopy() instead of inferring it.
fun customCopy(): Base = when (this) {
is X -> copy()
is Y -> copy()
}
customCopy has to return Base, otherwise the second code path can't compile. If you remove all non-X returning code paths (eg. by throwing an exception) the inferred type will become X instead.
It's quite unclear what problem you are really asking to solve, because your example should just call x1.copy() directly.

Why is subtype function overloading not possible with Kotlin sealed classes?

Let's say I have sealed class I'm using for a server response:
sealed class Response{
class Success: Response()
class ErrorA: Response()
class ErrorB: Response()
}
And a bogus response:
fun getResponse(): Response{
val r = Random()
return when (r.nextInt(3)) {
0 -> { Response.Success() }
1 -> { Response.ErrorA() }
2 -> { Response.ErrorB() }
else -> { throw IllegalStateException() }
}
}
And I want to handle the response. I currently could use something like this:
fun handle(response: Response) = when (response) {
is Response.Success -> { handle(response) }
is Response.ErrorA -> { handle(response) }
is Response.ErrorB -> { handle(response) }
}
Which the compiler will then ensure handles all cases. An awesome feature!
Why, though, could I not do something like this:
class ResponseHandler(){
fun handle(success: Response.Success) {}
fun handle(error: Response.ErrorB) {}
fun handle(error: Response.ErrorA) {}
}
and call
ResponseHandler().handle(response)
This achieves the same thing but does not compile, my question is this: in the same way that the compiler ensures, at runtime, that all cases are handled in a when statement, why can the same logic not be applied to method overloading?
Any information or referrals to further reading would be hugely helpful. Thanks
In principle it could be done (essentially by auto-generating the handle(response: Response) = when ... method). But I don't think it's ever likely to be. Overloading in Kotlin works basically the same as in Java/Scala/other JVM languages and introducing a major difference for so little benefit doesn't looks like a good idea (of course this doesn't apply to when which is Kotlin-specific).
If you want it, you can just define the same fun handle(response: Response) inside ResponseHandler (and make the other handle methods open so it's actually useful).
This problem can be broke down to this simplified example:
fun calc(i: Int) = i * 2
fun calc(d: Double) = d * 2
fun main(args: Array<String>) {
val i: Number = 5
calc(i)
}
You have two specialized methods that take an Int and Double respectively. Your value is of type Number (supertype of both, Int and Double). Although i obviously is an integer, your variable has a type Number, which cannot be an argument to either calc(i: Int) or calc(d: Double).
In your case, you get a Response and want to invoke one of the overloaded methods, none of which takes a Response directly.

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

Kotlin NullPointerException occurrence

I'm new to kotlin, I'm confused the situation at below when I starting to Null Safety.
There's some data inconsistency with regard to initialization (an uninitialized this available in a constructor is used somewhere).
Could anyone describe the situation more in detailed?
Example adapted from a Kotlin discussion on exactly this:
class Foo {
val c: String // Non-nullable
init {
bar()
c = "" // Initialised for the first time here
}
fun bar() {
println(c.length) // Oh dear
}
}
fun main(args: Array<String>) {
Foo()
}

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