Habs mir bisher nur im privaten angesehen und bin echt begeistert von der Sprache. Es hat zwar was von Java - fühlt sich aber nicht unbedingt danach an (dafür ist kotlin einfach viel moderner gestaltet).
Wovon ich ein großer Fan bin (auch wenn ichs bisher nur in Spielereien einsetzen konnte) ist die Möglichkeit eigene DSLs in Kotlin selber zu schreiben. Das fw kotlintest gebraucht es z.B. ganz gerne:
class MyTests : StringSpec() {
init {
"length should return size of string" {
"hello".length shouldBe 5
}
}
}
das obige wird mit extension methods und infix-functions erreicht. Das schöne, das ganze lässt sich mit einem scope umsetzen. D.h. extensions & co sind dann z.B. nur für eine bestimmte Klasse verfügbar.
KSKB:
fun main(args: Array<String>) {
// "funst hier nicht" {} <-- Geht nicht, da out of scope
MyTest()
// (3+5) shouldBe 5 <-- Ebenso hier: shouldBe ist außerhalb der Klasse Test nicht bekannt
}
class MyTest : Test() {
init {
"Successfull test" {
Thread.sleep(10)
(1+2) shouldBe 3
}
"shouldBe fails" {
(1+2) shouldBe 5
}
"Default exception" {
throw RuntimeException("Depp")
}
}
}
open class Test {
infix fun Any.shouldBe(value: Any) {
if(!this.equals(value)) {
throw RuntimeException("$this is not equal to $value")
}
}
operator fun String.invoke(testCase: () -> Unit) {
println("Execute test: $this")
val timeStamp = System.currentTimeMillis()
try {
testCase()
} catch(e: Exception) {
println("$this died with exception $e")
}
println("$this took ${System.currentTimeMillis() - timeStamp}ms")
println()
}
}
Ausgabe:
Execute test: Successfull test
Successfull test took 12ms
Execute test: shouldBe fails
shouldBe fails died with exception java.lang.RuntimeException: 3 is not equal to 5
shouldBe fails took 0ms
Execute test: Default exception
Default exception died with exception java.lang.RuntimeException: Depp
Default exception took 1ms
Process finished with exit code 0
Dinge die für den Alltag vllt etwas gebräuchlicher sind:
-
Data-klassen (für reine Datenhaltung. Implementieren dann direkt Sachen wie toString, equals und hashcode und bieten noch en paar mehr gimmiks.
-
Method delegation: man kann eine Klasse von einem Interface erben lassen, über den Konstruktor eine Implementierung angeben und mittels dem by-keyword weiß kotlin dann, dass alle methoden des interfaces an die implementierung delegiert werden sollen.
-
Felder mit “Überwachung”:
class Demo {
val abc: String by Delegates.observable(…)
}
nach dem by kannst du in diesem Fall eine Implementierung anbieten, welche das Verhalten vom getter/setter definieren. Für JavaFx kann man sich dann etwas schreiben, dass das hier funst:
val textProperty: StringProperty = SimpleStringProperty("")
val doneProperty: BooleanProperty = SimpleBooleanProperty(false)
var text: String by textProperty
var done: Boolean by doneProperty
In diesem Beispiel würde text = “abc” dazu führen, dass textProperty.setText(“abc”) aufgerufen würde.
Also kotlin hat schon einiges zu bieten. Würde auf jeden Fall empfehlen das mal anzuschauen.