Photo by Joshua Eckstein on Unsplash
In this new post from the Kotlin – Swift comparison series, we will talk about classes, the main building block in O.O.P languages.
In Kotlin
We use the reserved keyword “class“ to declare a class:
// class declaration
class User {
//XXX: body goes here
}
A class declaration contains several parts:
- a required name
- an optional header, in parentheses, after the class name
- an optional (but often needed…) body, in between curly braces.
Class name
It’s the only mandatory part in the class declaration, so the following code is valid too:
//XXX: class only with name
class User
Class header
It’s used to define at the same time:
- the primary constructor and its parameters
- the properties contained on each class instance
//XXX: class with header
class User(val firstname : String, val lastname : String, val nick : String = "no_nick")
As shown in the snippet, class properties can be either mutable or immutable. Default values can be assigned to each property when required.
The primary constructor differs from secondary constructors since it’s defined outside the class itself. It can be highlighted using the reserved keyword “constructor”:
//XXX: class with header using keyword
class User constructor(val firstname : String, val lastname : String, val nick : String)
Kotlin concise syntax allows us to define both the constructor and the class properties. In fact, the previous snippet can be rewritten into a more Java-style code that does exactly the same:
- declare a class named “User”
- declare a 3-parameter constructor to build instances of this class
- declare 3 String properties and set their values with the arguments received in the constructor
class User constructor(firstname : String, lastname : String, nick : String = "no_nick") {
//XXX: class props
val firstname : String
val lastname : String
val nick : String
//XXX: initialization
init {
this.firstname = firstname
this.lastname = lastname
this.nick = nick
}
}
As is frequently done, the ambiguity between parameter and property names is broken using the implicit reference “this“.
Class body
Contains:
- initialization block. Since the primary constructor in the class header cannot have any statements, we use this block to perform additional operations
- properties (when not declared in the class header)
- secondary constructors (declared inside the class)
- instance methods
Secondary constructors are generally used when the superclass forces us to do so, by overloading the main constructor. A common example is the superclass “View” on Android. When inheriting from this class or any of its descendants, we have to define several constructors:
class CustomTextView : TextView {
private var config : Config
constructor(cntxt : Context) : super(cntxt) {
//XXX: code here
}
constructor(cntxtx : Context, attrs : AttributeSet) : super(cntxt, attrs) {
//XXX: code here
}
//XXX: more constructor declarations here...
fun customizeView() {
//XXX: code here
}
}
Additionally, a class body can also contain:
- nested classes
- object declarations
Extra: data classes
Data classes in Kotlin are a special kind of class used to create POJOs:
//XXX: data class
data class User(val firstname : String, val lastname : String, val nick : String)
By adding the keyword “data” at the beginning, the class will automatically contain default implementations for:
- toString()
- equals()
- hashCode()
Moreover, in order to promote immutability, data classes also contain other methods like copy(), so we can create new instances based on existing objects:
val user1 = User(firstname = "John", lastname = "Dough")
val user2 = user1.copy(firstname = "Jane")//XXX: only change value on certain props, mantain the other ones
In Swift
The class declaration is identical, using the keyword “class” too:
class User {
//XXX: body here
}
But, in this case, the class declaration only contains:
- a name after the keyword
- a mandatory body, in between curly braces.
Class name
Since the body is mandatory too, we cannot define a class by only specifying its name:
//FIXME: error, missing body
class User
Class body
Includes:
- class properties, mutable or immutable
- initialization blocks
- instance methods
class User {
let firstname : String
let lastname : String
let nickname : String
init(firstname : String, lastname : String, nickname : String) {
self.firstname = firstname
self.lastname = lastname
self.nickname = nickname
}
func subscribe() -> Bool {
//XXX: code here....
return true
}
}
In this case, initialization blocks have params, so their syntax it’s kind a combination of constructors and initializers in Kotlin.
Inside the initialization block, in order to reference to the object being build, we use “self” (instead of this) in order to break the names ambiguity.
Wrapping up…
Class declaration syntax and semantics are very similar in both languages, being headers and initializers blocks the main differences between the two of them.
Kotlin introduces the class headers, so the resulting code is more compact and concise. On the other hand, class declarations in Swift contain some more boilerplate code.
On the other hand, classes in both languages have init blocks, but their format is slightly different.
As usual, you can find a sample code to play with in the following link: