Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: How can I use delegated properties in Java?

I know that you can't use the delegated property syntax in Java, and won't get the convenience of "overriding" the set/get operators as in Kotlin, but I'd still like to use an existing property delegate in Java.

For instance, a simple delegate of an int:

class IntDelegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>) = 0
}

In Kotlin of course we can use this like so:

val x by IntDelegate()

But how can we use IntDelegate in some form in Java? This is the start, I believe:

final IntDelegate x = new IntDelegate();

And then using the functions directly. But how can I use the getValue function? What do I pass for its parameters? How do I get a KProperty for Java field?

like image 654
Jire Avatar asked Jul 17 '17 23:07

Jire


People also ask

How do you use Kotlin delegate?

Android Dependency Injection using Dagger with Kotlin Kotlin supports “delegation” design pattern by introducing a new keyword “by”. Using this keyword or delegation methodology, Kotlin allows the derived class to access all the implemented public methods of an interface through a specific object.

What is delegated properties in Kotlin?

Delegate properties in Kotlin are basically regular properties that delegate how they are read and written to another function (think of getters and setters). From an Android development perspective, this can be used in powerful ways.

What is delegated property?

A property can delegate its getter and setter to another property. Such delegation is available for both top-level and class properties (member and extension). The delegate property can be: A top-level property. A member or an extension property of the same class.

What is delegate in Java?

Delegation is simply passing a duty off to someone/something else. Delegation can be an alternative to inheritance. Delegation means that you use an object of another class as an instance variable, and forward messages to the instance.


2 Answers

If you really want to know how Kotlin delegated property looks under the hood in Java, here it is: in this example a property x of a java class JavaClass is delegated to the Delegates.notNull standard delegate.

// delegation implementation details
import kotlin.jvm.JvmClassMappingKt;
import kotlin.jvm.internal.MutablePropertyReference1Impl;
import kotlin.jvm.internal.Reflection;
import kotlin.reflect.KProperty1;

// notNull property delegate from stdlib
import kotlin.properties.Delegates;
import kotlin.properties.ReadWriteProperty;


class JavaClass {
    private final ReadWriteProperty<Object, String> x_delegate = Delegates.INSTANCE.notNull();
    private final static KProperty1 x_property = Reflection.mutableProperty1(
            new MutablePropertyReference1Impl(
                JvmClassMappingKt.getKotlinClass(JavaClass.class), "x", "<no_signature>"));

    public String getX() {
        return x_delegate.getValue(this, x_property);
    }

    public void setX(String value) {
        x_delegate.setValue(this, x_property, value);
    }
}

class Usage {
    public static void main(String[] args) {
        JavaClass instance = new JavaClass();
        instance.setX("new value");
        System.out.println(instance.getX());
    }
}

However I wouldn't recommend to use this solution, not only because of the boilerplate required, but because it relies heavily on the implementation details of the delegated properties and kotlin reflection.

like image 126
Ilya Avatar answered Sep 23 '22 15:09

Ilya


I know that you can't use the delegated property syntax in Java, and won't get the convenience of "overriding" the set/get operators as in Kotlin, but I'd still like to use an existing property delegate in Java.

No, just like what you said in start, it does not exist in Java. But if you insist on doing it, you can do similar things.

public interface Delegate<T> {
    T get();
    void set(T value);
}

public class IntDelegate implements Delegate<Integer> {
    private Integer value = null;

    @Override
    public void set(Integer value) {
        this.value = value;
    }

    @Override
    public Integer get() {
        return value;
    }
}

final Delegate<Integer> x = new IntDelegate();

Delcare x in interface allows you to have different implementation.

like image 42
Joshua Avatar answered Sep 26 '22 15:09

Joshua