0

I have a an Interface in Java with the static variable interfaceValue that I could access as below

public class Experimenting {

    public interface MyInteface {
        int interfaceValue = 10;
    }

    class MyImpl implements MyInteface { }

    MyImpl myImpl = new MyImpl();

    void testing() {
        int getInterfaceValue = myImpl.interfaceValue;
    }
}

When I convert to Kotlin, it is as below

class Experimenting {

    internal var myImpl = MyImpl()

    interface MyInteface {
        companion object {
            val interfaceValue = 10
        }
    }

    internal inner class MyImpl : MyInteface

    internal fun testing() {
        val getInterfaceValue = myImpl.interfaceValue
    }
}

However the myImpl.interfaceValue is showing compile error sign, where by it doesn't recognize the interfaceValue. How could I still access my interfaceValue in Kotlin?

leonardkraemer
  • 6,573
  • 1
  • 31
  • 54
Elye
  • 53,639
  • 54
  • 212
  • 474

2 Answers2

1

The conversion converts the static final interfaceValue to a val in the companion Kotlins equivalent of that. Unfortunately the converter is not perfect and sometimes messes thing up. To access it

import com.your.package.Experimenting.MyInteface.Companion.interfaceValue    
class Experimenting {

    internal var myImpl = MyImpl()

    interface MyInteface {
        companion object {
           const val interfaceValue = 10
        }
    }

    internal inner class MyImpl : MyInteface

    internal fun testing() {
        val getInterfaceValue = interfaceValue
    } 
}

does the trick.

also does:

class Experimenting {

    internal var myImpl = MyImpl()

    interface MyInteface {
        companion object {
           val interfaceValue = 10
        }
    }

    internal inner class MyImpl : MyInteface

    internal fun testing() {
        val getInterfaceValue = MyInteface.interfaceValue
    }
}

A third way would be to copy the value of interfaceValue into the implementing class:

class Experimenting {

    internal var myImpl = MyImpl()

    interface MyInteface {
        companion object {
            const val interfaceValue = 10
        }
    }

    internal inner class MyImpl : MyInteface{
        val interfaceValue = MyInteface.interfaceValue
    }

    internal fun testing() {
        val getInterfaceValue = myImpl.interfaceValue
    }
}

Basically you access it like you would access a static variable in java.

leonardkraemer
  • 6,573
  • 1
  • 31
  • 54
  • Thanks. I like your answer, but that makes the `interfaceValue` no longer accessible from the implementor, which makes it different from what it was originally intended. I still give you a vote for the syntactically correctness of it. Thanks! – Elye Oct 24 '18 at 21:47
  • I have another answer, which I think mimic the original behavior. https://stackoverflow.com/a/52978332/3286489 Do check it out and let me think what your thought is. Thanks. – Elye Oct 24 '18 at 22:06
  • Your answer loosens the constraints on `interfaceValue` from `final` to `open`. Also It will no longer be static. – leonardkraemer Oct 24 '18 at 22:14
  • Agree, it is no longer syntatically correct. Though it is not final, it is not mutable too. Hence in practical, the usage would be more similar to the original Java version. – Elye Oct 24 '18 at 22:27
  • `final` in the sense that you cannot override or change it. You can not change the value of `interfaceValue` in the java interface either – leonardkraemer Oct 24 '18 at 22:35
0

I guess the right conversion of such Java code to Kotlin code should be as below

class Experimenting {

    internal var myImpl = MyImpl()

    interface MyInteface {

        val interfaceValue: Int
        get() = 10
    }

    internal inner class MyImpl : MyInteface

    internal fun testing() {
        val getInterfaceValue = myImpl.interfaceValue
    }
}

Though syntactically they are different, i.e. interfaceValue not really a static variable anymore, but practicality the same.

Elye
  • 53,639
  • 54
  • 212
  • 474
  • What this lets you do is override the `interfaceValue`. If this is what you want go for it. It really depends if the `interfaceValue` is constant for all `MyInterface`s (my answer and the behaviout as it is in java) or should be able to be overridden (this). – leonardkraemer Oct 24 '18 at 22:09
  • consider `internal inner class MyMyImpl : MyInteface{ override val interfaceValue : Int get() = 11 }` – leonardkraemer Oct 24 '18 at 22:12
  • I see, one could override it. You have the point, that the subtle different. – Elye Oct 24 '18 at 22:29
  • This is the kind of difference that causes hard to fix bugs. So if you do this do not assume it to be equal to the java code. – leonardkraemer Oct 24 '18 at 22:40
  • I guess in short Java != Kotlin, and Kotlin != Java. Both have its pro con. – Elye Oct 24 '18 at 22:43
  • I just noticed you can shadow the interface property in Java. So yeah, this comes closer to the Java version. But you can also do that in Kotlin – leonardkraemer Oct 24 '18 at 22:55
  • Can you provide more detail of what you mean? – Elye Oct 24 '18 at 22:58
  • ` internal inner class MyImpl : MyInteface{ val interfaceValue = 0 } internal fun testing() { val getInterfaceValue = myImpl.interfaceValue }` – leonardkraemer Oct 24 '18 at 22:59