Kotlin doesn't really have true reified generics (any more than e.g. Scala has), Java 8 has first class lambdas, extension methods and @Nullable now. Kotlin is just Java 8 with cleaner syntax.
I'm no expert on Java 8, but it looks like the new feature they call "extension methods" is just the ability to define methods in interfaces and inherit them, essentially like a concrete method in an abstract base class, isn't it?
The "extension methods" in Kotlin (and C#) is a completely different feature: syntactic sugar for static utility methods, which allow you to add new methods to any class without needing to modify the original class. (Or at least make it look that way syntactically.)
So in Kotlin you can do this:
fun String.toLeetSpeak(): String {
val charmap = mapOf('e' to '3', 'l' to '1')
return this.map { charmap[it] ?: it }.joinToString(separator="")
}
fun main(args: Array<String>) {
println("Hello!".toLeetSpeak())
}
...whereas in Java you would have to change (and have access to) the implementation of one of the classes or interfaces that String inherits from.
Also in Kotlin you can have extension methods with multiple receivers:
class Dictionary {
val wordList = setOf<String>()
fun String.isWord(word): Boolean =
word in wordList
}
...
val myDictionary = Dictionary()
with (Dictionary) {
println("dog".isWord)
}
(you can skip the "with" when being inside Dictionary)
> ...whereas in Java you would have to change (and have access to) the implementation of one of the classes or interfaces that String inherits from.
Or, you know, just define a plain function.
> which allow you to add new methods to any class without needing to modify the original class
No, those aren't methods, because they don't do dynamic dispatch. This is actually a problem in case you have an inheritance hierarchy and you want different behavior for a ChildClass extending a BaseClass.
Speaking of Scala, it's the only one out of the ones mentioned here that can do that based on the compile-time time, by letting you define the same extension for both ChildClass and BaseClass, but with different priorities, such that the compiler can disambiguate.
My comment was about extension methods and how the name refers to different features in Java and Kotlin, so I meant "...whereas in Java [if you wanted to use the Java feature to do the same thing the Kotlin feature by the same name does] you would have to ...".
> those aren't methods
I know, they're only sugar for static methods, as I said.
The @Nullable syntax is akin to putting a band-aid on a rotting leg. You cannot fix Java without breaking compatibility with older code. They only way to see it is not to look at the problem from the inside out when you have been surrounded with Java for perhaps decades in your career.
In my code null-pointer exceptions or similar accidents (force unwrapping something that simply doesn't exist) never happens anymore. Not in my libraries and not in my program code. A whole class of bugs just gone. Simply because I have to prove that something exists before I use it at compile time already.
It's like having security that starts with everything turned OFF for a default user instead of ON.
Kotlin has generics that are in most circumstances reified enough ;).
Optionals of Java8 and Guava are a terrible idea. @Nullable is just an annotation.
Null-safety built in the language is the only way to go.
You could always argue that a language is just cleaner syntax. Kotlin is a cleaner syntax for interacting with JVM-bytecode.
Scala is a also cleaner syntax for interacting with JVM-bytecode.
JVM-Bytecode is a cleaner syntax for interacting with operating systems.
Optional is a concept that you need even in a null-safe language (e.g. Haskell has Maybe). With language-level nullability you can sort-of emulate a pseudo-Optional type, but why would you want to? It's inherently second-class because it can't ever be properly compositional (Option[A] is always a different type from A and can be understood without knowing anything about A, whereas A? might or might not be a different type from A, you can't understand what it does without knowing the details of what A is).
Once you start interacting with JVM bytecode Kotlin ceases to have null-safety. @Nullable is just an annotation but at least you can write it down, unlike Kotlin's "platform types". Conversely if you're not interacting with non-Scala bytecode then Scala is null-safe in practice if not in theory, because the Scala ecosystem doesn't use null and has tools to enforce this.
I think it most real code you're better off without the Optional monad.
A variable being null is not a condition you can always a have a name for. You want to use it sometimes, but not built your entire vocabulary around it.
You also don't usually want to pass wrapped nulls around, you just want nulls available in local state.
> You want to use it sometimes, but not built your entire vocabulary around it.
Sure, which is why it should be an ordinary library type written in the language (and operated on with normal methods), not a magic special type with direct compiler support and custom operators.
> A variable being null is not a condition you can always a have a name for. You want to use it sometimes, but not built your entire vocabulary around it.
> You also don't usually want to pass wrapped nulls around, you just want nulls available in local state.
Why are you thinking in terms of "null" and "wrapping"? Think in terms of the business condition you want to represent. Often you have the possibility of some value being not-set or unknown in your data model - this comes up often enough that it's worth having a standard library type to represent it. "A variable being null" is not something that happens a priori, it's just an unfortunate representation certain languages adopt.
> Kotlin has generics that are in most circumstances reified enough ;).
They are not more reified than what you can achieve by just putting Class<T> fields in Java objects to represent the runtime type of the generic type parameter. Sure, Java solution is kinda more verbose and ugly, but this is basically what people already said here: Kotlin has some nice syntax sugar.
But you still can't have two different methods differing only with the generic type parameter (e.g. List<String> and List<Integer>). And the code is still not-specialized properly, read "slow".
Real reification will be possible if project Valhalla arrives (maybe Java 10, who knows?)
The "extension methods" in Kotlin (and C#) is a completely different feature: syntactic sugar for static utility methods, which allow you to add new methods to any class without needing to modify the original class. (Or at least make it look that way syntactically.)
So in Kotlin you can do this:
...whereas in Java you would have to change (and have access to) the implementation of one of the classes or interfaces that String inherits from.