Reputation: 75
I'm currently writing a KOTLIN class were I like to use the possibility of DSL but be backwards compatible for JAVA developers. When using a var
the compiler automatically creates getter and setter for JAVA, but those can't be used Builder style since they are not returning this
.
So basically what I like to do is something like this:
class MyClass {
// for use in KOTLIN only DSL style e.g. MyClass() { offset = 1 }
var offset: Int? = null
// for use in JAVA only BUILDER style e.g. new MyClass().withOffset(1)
fun withOffset(value: Int) = apply { offset = value }
}
In Kotlin I like to use, but don't want to have access to the withOffset
fun:
val myClass = MyClass() { offset = 1 }
In JAVA I like to use, but don't want to have access to the auto created setOffset
and getOffset
:
MyClass myClass = new MyClass().withOffset(1)
Renaming the getter and setter is possible via @JvmName
annotation already, but is there a annotation for hiding a public property for JAVA completly and optional of course vice versa?
Upvotes: 4
Views: 565
Reputation: 8106
You cannot hide a constructor, while you can make a so called fake-constructor using operator fun invoke
in which you can use a @JvmSyntheic annotation to hide it from the java.
And to hide a function from kotlin you can use @Deprecated with DeprecationLevel.HIDDEN.
Note: The @JvmField will instruct the compiler not to generate the default getter and setter for your var
class MyClass {
@JvmField
var offset: Int? = null
@kotlin.Deprecated(message = "JUST FOR JAVA", level = DeprecationLevel.HIDDEN)
fun withOffset(value: Int) = apply { offset = value }
companion object {
@JvmSynthetic
operator fun invoke(init: MyClass.() -> Unit) = MyClass().apply(init)
}
}
Usage in kotlin:
MyClass() { offset = 1 }
// or
MyClass { offset = 1 }
Usage in java:
MyClass().withOffset(1)
Resources:
Upvotes: 2
Reputation: 1086
It's not possible to do something like this in Kotlin
val myClass = MyClass() { offset = 1 }
but I would suggest you do do this instead, it looks much nicer in my opinion.
// It's a inline function so there's no runtime overhead.
inline fun buildMyClass(builder: MyClass.() -> Unit): MyClass {
return MyClass().apply(builder)
}
class MyClass {
@JvmSynthetic
var offset: Int? = null
private set
fun withOffset(value: Int) = apply { offset = value }
}
So you can call it like below
val myClass = buildMyClass {
withOffset(0)
}
In Java, it looks like this:
final MyClass myClass = new MyClass().withOffset(0);
Upvotes: 1