Example:
In C-code it is possible to call parts of assembler code, like:
int main()
{
//... stuff
__asm
{
lea ebx, hal
mov ecx, [ebx]hal.same_name ;
mov esi, [ebx].weasel ;
}
// .. further stuff
return 0;
}
Is such a code integration possible for Kotlin code in Java (*.java) files?
(I am not talkin about JNI or C/C++ in Java!)
I would like to extend already existing (AndroidStudio-) Java-Source-Code with Kotlin language.
//.. this is *.java file
public class MyAlreadyExistingJavaClass {
private int memberVar;
public MyAlreadyExistingJavaClass()
{
}
// this is Kotlin within *.java file
// extend this Java file with this constuctor in KOTLIN ?
// would make above default constructor unneccessary.
class MyAlreadyExistingJavaClass(number: Int = 0)
{
memberVar = number;
}
}
Java does not provide any syntax for including snippets of code in Kotlin or any other language into a Java file. However, this is not necessary to accomplish your task. You can simply define the constructor you need as a factory function in a separate Kotlin file:
fun MyAlreadyExistingJavaClass() = MyAlreadyExistingJavaClass(0)
If you want to define a new method, rather than a constructor, you can use extension functions.
I am a Groovy developer, not a Kotlin developer, but it looks like Kotlin provides a scripting API. Groovy, JavaScript and JRuby can all be called from within a Java class using the standard Java ScriptEngine API. You would want something like that to approximate inlining Kotlin within a Java class. I say approximate because it wouldn't be run directly like that assembly example, but would be passed through a ScriptEngine-compliant Kotlin implementation.
Related
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
You need to specify interface explicitly:
fun foo() = println(JSubsystem.IRIS)
Or you can import constant explicitly:
import your.package.name.JSubsystem.IRIS
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.
Short question
Can I modify the visibility of a Kotlin object's INSTANCE (for Java interop) to internal or lower?
Long question
I'm writing a library and I want to have an API file / class, written in Kotlin, that exposes a function to be called from either Java or Kotlin like this:
Kotlin:
API.function()
Java:
API.function();
I can achieve this by writing it like this:
Kotlin:
object API {
#JvmStatic
fun function() = TODO()
}
However, now I can also do this:
Java:
API.INSTANCE.function();
I want to prevent this access to INSTANCE to keep my API surface to a minimum for simplicity.
Can I modify the visibility of INSTANCE to internal or lower?
It's probably not possible, because any call to API (from Kotlin) returns the object's instance and that should probably be hidden too for this to be possible. However, I'm curious to see if it is without major hacks.
A solution using Java would be to write API in Java:
public final class API {
private API() {
}
public static void function() {
}
}
However, I'm looking for a solution written in Kotlin.
The closest I could come up with was something like this:
Create a file API.kt in a package com.example.api. Add your functions directly into that file, like this:
#file:JvmName("API")
package com.example.api
fun function() {
// ...
}
Kotlin:
You can import that function anywhere you need to use your api:
import com.example.api.function
Though you can't use your syntax API.function anymore.
Java:
The generated class would look something like this (no singleton, just static methods, but no private constructor):
public final class API {
public static final void function() {
// ...
}
}
Which then allows you to call it like API.function();
By specifiying #file:JvmName("API") you instruct kotlin to name the created class API.
I'm new to annotation processing and code generation. I want to find out how can I perform such operation like appending new method to existing class. Here is an example of what I want to do:
Assume that we have a class with with custom annotations like this one:
class SourceClass {
#CustomAnnotation
fun annotatedFun1(vararg argument: Any) {
//Do something
}
#CustomAnnotation
fun annotatedFun2(vararg argument: Any) {
//Do something
}
fun someOtherFun() {
//Do something
}
}
And the result I want to get - extended copy of that class:
class ResultClass {
fun hasFunWithName(name: String): Boolean {
return (name in arrayOf("annotatedFun1", "annotatedFun2"))
}
fun callFunByName(name: String, vararg arguments: Any) {
when (name) {
"annotatedFun1" -> annotatedFun1(*arguments)
"annotatedFun2" -> annotatedFun2(*arguments)
}
}
fun annotatedFun1(vararg argument: Any) {
//Do something
}
fun annotatedFun2(vararg argument: Any) {
//Do something
}
fun someOtherFun() {
//Do something
}
}
I've already found out how to create annotation processor. I'm looking for a method to save all existing fields, properties and methods in source class and to append a few more methods to it.
If it is possible to modify class without creating new one - it would be perfect, but in all tutorials only new classes are created and I didn't find any example where all contents of source class are being copied to another one.
Please, do not advise to use reflection. I need this for android and so reflection is not the option cause of resources cost. I'm looking for compile-time solution.
It is required for custom script language implemented in app and should be used to simplify wrapper classes structure. When this job is done directly in code - it looks awful when such method count exceeds 20 per class.
Here is a good example of Java Annotation Processing I recently worked with.
It's an implementation of #Immutable annotation.
Check out ByteBuddy or Kotlin Poet to understand how additional code generation works.
For Kotlin you do almost the same, check this manual for Kotlin-specific steps.
With Kotlin, you can use extension functions and that is the recommended way of adding new functionality to existing classes that you don't control. https://kotlinlang.org/docs/reference/extensions.html
You may be abel to follow the pattern used by Project Lombok. See How does lombok work? or the source code for details.
Another option would be to write a new class that extends your source class:
class ResultClass : SourceClass {
fun hasFunWithName(name: String): Boolean {
return (name in arrayOf("annotatedFun1", "annotatedFun2"))
}
fun callFunByName(name: String, vararg arguments: Any) {
when (name) {
"annotatedFun1" -> annotatedFun1(*arguments)
"annotatedFun2" -> annotatedFun2(*arguments)
}
}
}
Or perhaps use composition instead and implemnent cover methods for all the public methods in SourceClass.
If you are not tied to doing this using annotation processing, you could use a separate piece of custom code to process the source code files before compiling. Maybe use a regular expression like /#CustomAnnotation\s+.*fun (\w+)\s*\(([^)]*)\)/gm (Test on Regex101) to find the annotated methods.
If I understood the requirement correctly, the goal is to implement something like described below.
You have a source file C.java that defines the class C like this:
public final class C
{
#Getter
#Setter
private int m_IntValue;
#Getter
#Constructor
private final String m_Text;
}
And now you want to know how to write an annotation processor that jumps in during compilation and modifies the source from C.java that the compiler sees to something like this:
public final class C
{
private int m_IntValue;
public final int getIntValue() { return m_IntValue; }
public final void setIntValue( final int intValue ) { m_IntValue = intValue; }
private final String m_Text;
public final String getText() { return m_Text; }
public C( final String text ) { m_Text = text; }
}
The bad news is, that this is not possible … not with an annotation processor, not for Java 15.
For Java 8 there was a way, using some internal classes with reflection to convince the AP to manipulate the already loaded source code in some way and let the compiler compile it a second time. Unfortunately, it failed more often than it worked …
Currently, an annotation processor can only create a new (in the sense of additional) source file. So one solution could be to extend the class (of course, that would not work for the sample class C above, because the class itself is final and all the attributes are private …
So writing a pre-processor would be another solution; you do not have a file C.java on your hard drive, but one named C.myjava that will be used by that preprocessor to generate C.java, and that in turn is used by the compiler. But that is not done by an annotation processor, but it may be possible to abuse it in that way.
You can also play around with the byte code that was generated by the compiler and add the missing (or additional) functionality there. But that would be really far away from annotation processing …
As a summary: today (as of Java 15), an annotation processor does not allow the manipulation of existing source code (you cannot even exclude some source from being compiled); you can only generate additional source files with an annotation processor.
I need to create some extension methods in my Java code. I've read some posts here in SO and people suggest XTend or Scala in order to achieve this.
Now, my question would be.. if i write kind of an Adapter layer in Scala (adding there my extension methods) and then using that project as a dependency for my own Java project, are those extended methods available for me to use, or they are defined just for the 'scope of Scala project' and then the JVM output cannot provide those new methods to the other project using it?
EDIT:
What i need to do is to extend a full hierarchy of classes in a given library and give some new functionality. As for Java's first approach I should extend every class in that hierarchy creating my own hierarchy of extended classes adding the new method there. I would like to avoid this and give the final user the sense of native functionality in the original hierarchy.
Regards.
As mentioned above in the comments, it is very close to C# but not exactly there because of the type erasure. For example, this works fine:
object myLibExtensions {
implicit class TypeXExtension( val obj: TypeX ) extends AnyRef {
def myCustomFunction( a: String ): String = {
obj.someMethod(a)
}
}
}
It will act somewhat similar to C# extension methods, i.e. create static method wrappers in reasonable cases (but not always).
The only thing I am missing in Scala is that you can't (or at least I couldn't figure out how to) return the values of the types being extended. For example, assume I want to have something like an extension method "withMeta" that works as follows:
class TypeY extends TypeX { def methodOfY(...) ...}
var y: TypeY = ....
y.withMeta(...).methodOfY(...)
The following didn't work for me:
object myLibExtensions {
private val something = ....
implicit class Extension[T<:TypeX]( val obj: T ) extends AnyRef {
def withMeta( meta: Meta[T] ): T = {
something.associateMeta(obj,meta)
val
}
}
}
... because T is being erased to TypeX. So effectively you will have to write extensions for all specific leaf classes of the hierarchy in this case, which is sad.
I'm developing a JavaFX8 application in Scala but I couldn't figure out how to pass a method reference to an event handler. To clarify, I'm not using ScalaFX library but build my application directly on top of JavaFX.
Here's the related code snippet.
InputController.java (I wrote this test class in Java to isolate the issue to consume a method reference only)
public class InputController {
public void handleFileSelection(ActionEvent actionEvent){
//event handling code
}
public InputController() {
//init controller
}
}
This works (Java)
InputController inputController = new InputController();
fileButton.setOnAction(inputController::handleFileSelection);
This doesn't work (Scala)
val inputController = new InputController
fileButton.setOnAction(inputController::handleFileSelection)
Here's the error message from the compiler (Scala 2.11.6).
Error:(125, 45) missing arguments for method handleFileSelection in class Main;
follow this method with '_' if you want to treat it as a partially applied function
fileButton.setOnAction(inputController::handleFileSelection)
^
If I use Scala 2.12.0-M2 instead, I get a different error message.
Error:(125, 45) missing argument list for method handleFileSelection in class Main
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `handleFileSelection _` or `handleFileSelection(_)` instead of `handleFileSelection`.
fileButton.setOnAction(inputController::handleFileSelection)
^
Is there a native way which Scala can leverage method references introduced in Java 8? I'm aware of the implicit conversions approach to use a lambda expression but I want to know if there is a way to use a method reference similar to Java 8 without needing to use the lambda decleration.
inputController::handleFileSelection is Java syntax, which isn't supported or needed in Scala because it already had a short syntax for lambdas like this: inputController.handleFileSelection _ or inputController.handleFileSelection(_) (inputController.handleFileSelection can also work, depending on the context).
However, in Java you can use lambdas and method references when any SAM (single abstract method) interface is expected, and EventHandler is just such an interface. In Scala before version 2.11 this isn't allowed at all, in 2.11 there is experimental support for using lambdas with SAM interfaces, which has to be enabled using -Xexperimental scalac flag, and starting from 2.12 it is fully supported and doesn't need to be enabled.
You should pass function which applying one parameter of type ActionEvent:
val button = new Button()
val inputController = new InputController()
def handler(h: (ActionEvent => Unit)): EventHandler[ActionEvent] =
new EventHandler[ActionEvent] {
override def handle(event: ActionEvent): Unit = h(event)
}
button.setOnAction(handler(inputController.handleFileSelection))
If you want a method reference that also takes the class instance as a parameter, for instance like String::length in Java, you can do (_:String).length which is equivalent to (s:String) => s.length().
The types of these are in Java Function<String, Integer> and in Scala thus String => Int.
Could you try
fileButton.setOnAction(() => inputController.handleFileSelection())