0

Why accessing constants defined in java interface from kotlin interface is not allowed or at least I am not able to access it. Is there any other way?

(Yes,I know The constant interface pattern is a poor use of interfaces from Effective Java book)

Following code (java) compiles

// ==== JSubsystem.java ====

public interface JSubsystem {
    String IRIS = "IRIS";
    String TCS = "TCS";
    // ...
}

// ==== JComponentType.java ====
public interface JComponentType {
    String HCD = "HCD";
    String Assembly = "Assembly";
    // ...
}

interface Demo extends JSubsystem {
    default void foo() {
        System.out.println(IRIS);
    }
}

But in the following kotlin interface which extends from java, IRIS|TCS|HCD is not accessible

// ==== AllModels.kt ====

interface AllModels : JSubsystem, JComponentType {
    fun foo() = println(IRIS)
}

More context on why we ended up at this situation:

We have a large scala codebase, all the models provide java and scala access.

Now we have scripting requirement for 1-5% of our users where we have utilised kotlin's scripting (.kts), dsl, coroutines and suspension features

We have provided script construct inside which users will have access to complete DSL and all the models.

We do not want users to explicitly import models from different files and we do not want to repeat defining models again in kotlin.

One of the solution we thought could work in this case is having java models (these are simple delegations to scala models) in interface and then have one interface at kotlin side which extends from all these java model interfaces and then script can be receiver of this interface - AllModels

1
  • println(JSubsystem.IRIS) ? Commented Jan 27, 2020 at 11:17

2 Answers 2

3

You need to specify interface explicitly:

fun foo() = println(JSubsystem.IRIS)

Or you can import constant explicitly:

import your.package.name.JSubsystem.IRIS

Sign up to request clarification or add additional context in comments.

3 Comments

As per the context provided in original post, We do not want users to explicitly import models from different files and we do not want to repeat defining models again in kotlin. This is in context of kotlin's script support. IRIS, TCS etc should be directly available in script without any import
@PritamKadam Can't do I suppose. Kotlin scripts are still Kotlin.
@xinaiz You can actually, see my answer.
2

You can customize your script environment as described in https://github.com/Kotlin/KEEP/blob/master/proposals/scripting-support.md, in particular you can add imports which will be automatically available with defaultImports.

This example in the Kotlin discussion forum should be helpful:

First, you need to create a script definition - a separate jar that describes your script “template”, e.g. similar to the https://github.com/JetBrains/kotlin/tree/master/libraries/tools/kotlin-main-kts Your definition may look something like:

@KotlinScript(fileExtension = "custom.ext", compilationConfiguration = ScriptConfiguration::class)
abstract class MyScript(val bindings: Map<String, Any?>) {
    val ortResult = bindings["ortResult"] as OrtResult
    val evalErrors = mutableListOf<OrtIssue>()
}

object ScriptConfiguration : ScriptCompilationConfiguration(
    {
        defaultImports("com.here.ort.model.*", "java.util.*")
        ide {
            acceptedLocations(ScriptAcceptedLocation.Everywhere)
        }
    })

It is a good idea to have a dedicated extension for your scripts (“custom.ext” in the example above), since IDE distinguish scripts by the extension.

Then you’ll need to create your own JSR-223 factory the same way as here - https://github.com/JetBrains/kotlin/blob/master/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineFactoryExamples.kt#L28, but use your script definition (MyScript) in place of KotlinStandardJsr223ScriptTemplate. You probably can do it in the same jar. And you need to register it in the services folder, of course.

You’ll still need a postface part in your evaluator though, but it seems not relevant to the IDE.

Then finally you need to supply Intellij with the definition. The simplest ad-hoc way to do it is to specify the FQN of your definition class along with the classpath needed to load it in the kotlin compiler settings -> “Kotlin scripting” in Intellij.

2 Comments

Thank you, In the end I went through this repo github.com/bamboo/kotlinconf2019 which satisfied my requirement
If it was sufficient, perhaps you should accept the answer?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.