NSMutableArray, among many other mutable variations on standard types. In Swift, you
let a collection and let the compiler handle the rest of the details, whether the outcome is mutable or not. Kotlin follows the Cocoa model. It uses distinct collection types based on mutability.
For example, the
listOf function returns a new read-only serializable list of elements.
val myList: List<Double> = listOf(1.0, 2.0, 3.0)
You cannot automatically promote typeless literals the way you can in Swift. In Swift the literal “
1” doesn’t have an intrinsic type (although it defaults to
Int in the absence of any other context). “
1” can represent an integer, a double, a float, and more.
Kotlin does not support literal inference. If you use
listOf(1, 2, 3) for the preceding example, Kotlin issues an error: “Type inference failed. Expected type mismatch: inferred type is List<Int> but List<Double> was expected”.
Like Swift, Kotlin’s type inference system permits you to drop the explicit
List<Double> type annotation from the
myList declaration. The
listOf function still produces the expected type, which the compiler assigns to the constant
myList. In this declaration, Kotlin’s
val is the same as Swift’s
let. It produces a constant rather than a (
However, the list you produced is not a value type. Switch the list from immutable to mutable, and you’ll still (like an
NSMutableArray reference) be able to add new members:
val myList: MutableList<Double> = mutableListOf(1.0, 2.0, 3.0)
println(myList) // [1.0, 2.0, 3.0, 4.0]
You won’t be able to re-assign
myList to a new list, but as a mutable reference type, the underlying instance can be modified because it is a
Kotlin also offers dictionaries, which it calls maps. That’s really not a bad name for a type that performs one-to-one mapping, which is all that key-value lookup really does. The underlying types honor that key/value relation. They’re called
Map<K, out V> and
val myDictionary = mutableMapOf(
"cow" to "moo",
"dog" to "woof",
"pig" to "oink"
println(myDictionary["dog"]) // woof
println(myDictionary["kitten"]) // null
Like Swift, Kotlin returns a “not there” result for a failed map lookup, but the meaning of
null is distinct from Swift’s
nil. A type must be nullable (sort of but not entirely like
Optional) to store a null reference.
var string = "Hello"
// string = null
// error: null can not be a value of a non-null type String
var string2: String? = "Hello"
println(string2) // hello
string2 = null
println(string2) // null
The initial value of
string2 is not
Optional("hello") or something like that. It feels (at least so far, because I know nothing about Kotlin, see the title of this post) more like the Objective-C
nil, that is a null-reference in memory rather than a pointer to a reference type. I’m new to this, so I’m still learning.
null, the first
string example demonstrates what happens when you assign
null to a non-nullable type. You end up with a (more or less) null pointer exception, which is a bad thing.
Getting back to collections, Kotlin also supports sets, both mutable and immutable. All three types: lists (arrays), maps (dictionaries) and sets (sets), inherit from Kotlin
Collection, and in turn from Kotlin
Iterable. All three types have a way to count the number of elements (or entries), they can be iterated over, and
Collection offers many methods that may or may not apply to each type. For example, you don’t use
dropWhile on a map/dictionary.
The Collections reference page lists which functions apply to which types. It’s a bit hodgepodge compared to Swift’s cleaner, hierarchical, and protocol-based system. That said, all the things you would expect to do to an array, set, or dictionary in Swift, you can do to a list, set, or map in Kotlin. Have a browse through that Collections page to get a sense of the functionality. It’s all pretty familiar.
If anything, the various subtypes (
IntArray, etc) feel like overkill and the available functions feel a tiny bit bloated. But that’s me looking at this stuff with Swift-ized eyes.
If you like this series of posts, let me know. Drop a tweet, email, or comment if you’d like me to keep going.