How to get kotlin function's caller - kotlin

With this example:
open class Parent {
fun some():Parent {
return this;
}
}
class A : Parent(){
val name:String? = null;
}
But then this code results in an error:
val a = A().some().some()
a.name // ERROR
EDITOR NOTE: based on comments of the author to answers below, the question is NOT about referencing a.name but really is about something like "how do I get the instance of the class or its name that first started the chain of method calls". Read all comments below until the OP edits this for clarity.
my final goal is to return caller's type and can call this caller's instance property, no more as , no more override, any idea?

Just like java, you can use stackTrace's getMethodName(). Refer to the kotlin doc.

Actially your example is working(if you add open keyword because all classes in Kotlin are final by default:
A.kt
open class A {
fun some(): A {
return this
}
}
B.kt
class B : A() {
val test = "test"
}
And usage
val tmpB = (B().some().some() as B)
val test = tmpB.test
Edited:
It because function some() return parent class which doesn't have child class property. So you need to cast it to child class.(Update code)

open class Parent{
open fun foo(): Parent {
return this;
}
}
This is your Parent class. Parent class has a method named foo(). foo() is a method of class A which will return the instance of it's own class. We must have to open the class and method because by default their visibility modifier is final.
class A : Parent() {
override fun foo(): A { return this }
}
This is a class named A which extends Parent class. foo() is a method of class A which will return the instance of it's own class.
We will call it like this:
var a = A().foo().foo()

Your class always return Parent instance. This class do not have any field with the name name. To do that you have 2 ways:
The first:
open class Parent{
fun some():Parent{
return this
}
}
class A :Parent(){
val name:String? = null
}
fun main() {
val a = (A().some().some() as A)
a.name = "";
}
The second:
open class Parent{
open fun some():Parent{
return this
}
}
class A :Parent(){
override fun some():A {
return this
}
val name:String? = null
}
fun main() {
val a = A().some().some()
a.name = "";
}

i have know how to do this:
#Avijit Karmakar
#Trần Đức Tâm
use inline function
inline fun <reified T:Any> some(sql: String):T {
return this as T ;
}

Related

Kotlin: Can I overwrite a function with another function? (like override)

I'm a Kotlin beginner.
I am not sure if the way I try is correct.
Now I want to override and capturing variables.
Suppose this is a method of SOMETHING class that can be overridden:
fun whoAreYou() {}
And this is my function:
fun thisFuntionsIs(): ()->Unit {
var i = 0
println("It's parent Function!")
return { println("It's child Function! ${i++}") }
}
Now I tried to override the existing function with the new one:
fun whoAreYou() = thisFuntionsIs() // Suppose used the override keyword
Now when I run this function it prints out a "parent" message every time.
This is not what I wanted.☹
If whoAreYou was a property, not a method, it would have been worked I wanted.
class SOMETHING {
var whoAreYou = ()->{} // If it was a property...
// fun whoAreYou() {} // But the current situation is
}
SOMETHING.whoAreYou = thisFuntionsIs()
SOMETHING.whoAreYou() // Yea~ I wanted that
Is there a solution? Or am I totally wrong? Please help me.
In order to override, you need to make your parent class and function open, then override the function in an extended class:
open class Parent {
protected var counter = 0;
open fun whoAreYou() = "It's parent Function!"
}
class Child : Parent() {
override fun whoAreYou() = "It's child Function! ${counter++}"
}
fun main() {
val parent: Parent = Parent()
val child: Parent = Child()
println(parent.whoAreYou()) // It's parent Function!
println(child.whoAreYou()) // It's child Function! 0
println(child.whoAreYou()) // It's child Function! 1
println(child.whoAreYou()) // It's child Function! 2
}
The code works. Maybe you just misinterpret results. Slightly modified version:
fun main(args: Array<String>) {
val x = SOMETHING()
x.whoAreYou = thisFuntionsIs()
x.whoAreYou()
x.whoAreYou()
}
class SOMETHING {
var whoAreYou = fun() {
System.out.println("It's parent Function!")
}
}
fun thisFuntionsIs(): () -> Unit {
var i = 0
System.out.println("It's Function!")
return { System.out.println("It's lambda! ${i++}") }
}
Output:
> It's Function!
> It's lambda! 0
> It's lambda! 1
The line x.whoAreYou = thisFuntionsIs() means that thisFuntionsIs is called and x.whoAreYou is assigned to anonymous function return by thisFuntionsIs.

Clean way to access outer class by the implementing delegate class

I was thinking about such case (accessing outer class which uses current class to implement some stuff):
interface Does {
fun doStuff()
}
class ReallyDoes: Does {
var whoShouldReallyDo: Does? = null
override fun doStuff() {
println("Doing stuff instead of $whoShouldReallyDo")
}
}
class MakesOtherDo private constructor(other: Does, hax: Int = 42): Does by other {
constructor(other: ReallyDoes): this(other.also { it.whoShouldReallyDo = this }, 42)
}
fun main(args: Array<String>) {
val worker = ReallyDoes()
val boss = MakesOtherDo(other = worker)
boss.doStuff()
}
Expected output:
Doing stuff instead of MakesOtherDo#28a418fc
But can't do that, because of error:
Error:(15, 79) Cannot access '' before superclass constructor
has been called
Which targets this statement: other.also { it.whoShouldReallyDo = this }
How can I (if at all) fix above implementation?
The reason for the error is other.also { ... = this } expression accesses this of type MakeOtherDo and is also used as argument to MakeOtherDo constructor. Hence, this will be accessed as part of MakeOtherDo (unary) constructor before this has been initialized as an instance of Does (super)class.
Since the assignment does not affect the initialization of the super class, you can executed it in the constructor of MakesOtherDo after the super class has been initialized.
class MakesOtherDo private constructor(other: Does, hax: Int = 42): Does by other {
constructor(other: ReallyDoes): this(other, 42) {
other.also { it.whoShouldReallyDo = this }
}
}
It took me a few minutes to decipher what you were doing above, and really the problem has nothing to do with delegates. You can simplify it down to this:
class Wrapper(var any: Any? = null)
class Test(val wrapper: Wrapper) {
constructor(): this(Wrapper(this)) // Cannot access "<this>" before superclass constructor has been called
}
The concept of "this" doesn't exist yet when we're still generating arguments for its constructor. You just need to move the assignment into the block of the constructor, which is code that's run after this becomes available:
class Test(val wrapper: Wrapper) {
constructor(): this(Wrapper()){
wrapper.any = this
}
}
Or in the case of your example:
constructor(other: ReallyDoes): this(other, 42){
other.whoShouldReallyDo = this
}

Get a reference to the class of the calling function

When I have two classes (A and B) and A has a function called myFunA which then calls myFunB (inside of class B), is it possible for code in myFunB to obtain a reference to the class A that is used to call myFunB? I can always pass the reference as a parameter but I am wondering if Kotlin has a way of allowing a function to determine the instance of the parent caller.
class A {
fun myFunA() {
val b = B()
b.myFunB() {
}
}
}
class B {
fun myFunB() {
// Is it possible to obtain a reference to the instance of class A that is calling
// this function?
}
}
You can do it like this:
interface BCaller {
fun B.myFunB() = myFunB(this#BCaller)
}
class A : BCaller {
fun myFunA() {
val b = B()
b.myFunB()
}
}
class B {
fun myFunB(bCaller: BCaller) {
// you can use `bCaller` here
}
}
If you need a reflection-based approach, read this.

Get companion class in companion object

Is there a way to get the javaClass of the companion class inside a companion object without knowing it's name?
I suppose I could get it by doing something like this:
open class TestClass {
companion object {
init {
val clazz = Class.forName(this::class.java.canonicalName.removeSuffix(".Companion"))
}
}
}
However, this does not work for class InheritingClass : TestClass(). It would still give me TestClass, not InheritingClass.
I was hoping for something more straightforward like this::class.companionClass.
Getting the class of the companion object of a given class will look like this:
TestClass::class.companionObject
Here's an example:
class TestClass {
companion object {
fun sayHello() = "Hello world"
}
}
If you want to get the class that contains the companion, since the latter is always an inner class of the former,
class TestClass {
companion object {
fun whichIsMyParentClass() = this::class.java.declaringClass // It'll return TestClass
}
}
And to further simplify, you'll also want to create an extension property:
import kotlin.reflect.KClass
val <T : Any> KClass<T>.companionClass get() =
if (isCompanion)
this.java.declaringClass
else
null
So, whenever you want to get the parent class of the companion object,
class TestClass {
companion object {
fun whichIsMyParentClass() = this::class.companionClass // It'll return TestClass
}
}
The companion class itself has no reference to the actual class as you can see in this bytecode
public final class TestClass$Companion {
private TestClass$Companion() { // <init> //()V
<localVar:index=0 , name=this , desc=LTestClass$Companion;, sig=null, start=L1, end=L2>
L1 {
aload0 // reference to self
invokespecial java/lang/Object <init>(()V);
return
}
L2 {
}
}
public TestClass$Companion(kotlin.jvm.internal.DefaultConstructorMarker arg0) { // <init> //(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
<localVar:index=0 , name=this , desc=LTestClass$Companion;, sig=null, start=L1, end=L2>
<localVar:index=1 , name=$constructor_marker , desc=Lkotlin/jvm/internal/DefaultConstructorMarker;, sig=null, start=L1, end=L2>
L1 {
aload0 // reference to self
invokespecial TestClass$Companion <init>(()V);
return
}
L2 {
}
}
}
The reference is only the other way around (see decompiled kotlin class)
public final class TestClass {
public static final Companion companion = ...
}
So you can either do it as you just did by cutting off the .Companion part of the class name or you reference it by hard with TestClass::class.java (what is in my opinion no problem and the best solution)
If you need to print the class name, you can add simpleName, such as
this::class.java.declaringClass.simpleName

Kotlin: How can I call super's extension function?

How can I call a super's extension function?
For example:
open class Parent {
open fun String.print() = println(this)
}
class Child : Parent() {
override fun String.print() {
print("child says ")
super.print() // syntax error on this
}
}
Even though the print() function is defined inside of Parent, it belongs to String, not to Parent. So there's no print function that you can call on Parent, which is what you're trying to do with super.
I don't think there's syntax support for the type of call you're trying to do in Kotlin.
It is not possible for now, and there is an issue in the kotlin issue-tracker - KT-11488
But you can use the following workaround:
open class Parent {
open fun String.print() = parentPrint()
// Declare separated parent print method
protected fun String.parentPrint() = println(this)
}
class Child : Parent() {
override fun String.print() {
print("child says ")
parentPrint() // <-- Call parent print here
}
}