The visibility of Java and Kotlin is slightly different.
public
package private
in KotlinLet's define a Dog class that inherits the Animal class in Kotlin.
open class Animal { //Add open to make it an inheritable class
open fun greet() { //Add open to make it an overridable function
}
}
class Dog: Animal() { //A colon followed by the parent class name
override fun greet() { //Add override modifier
println("Bow wow")
}
}
When inheriting a class
class subclass name
: Write as superclass constructor
.
Let's look at the case where the constructor requires arguments.
open class Animal(val name: String) {
open fun greet() {
}
}
//Dog constructor argument`name`To the constructor of the Animal class
class Dog(name: String): Animal(name) {
override fun greet() {
println("Bow wow")
}
}
Kotlin does not have a static modifier.
If you want to handle static members and static functions in Kotlin classes, Use a companion object.
What is a companion object? A special singleton instance.
class Dog {
companion object {
val ancestorName: String = "wolf"
}
fun greet() {
println("Bow wow")
}
}
val ancestor = Dog.ancestorName
I have defined a property called ʻancestorNamein the
companion object. To access this property, access
Dog.ancestorName` as if it were a static member.
Kotlin has a mechanism to easily implement a singleton.
object ResourceManager {
fun clean() {
// ...
}
}
ResourceManager.clean()
You can define a singleton class following the ʻobject` keyword. You can define properties and functions like a regular class, but Only the constructor cannot be defined in the object declaration. Use the class name to access the singleton instance. Similar to accessing static members in Java.
You often implement simple classes for holding data, right?
data class Point(val x : Int,
val y: Int) {
}
Define the class after the data
keyword.
The data class considers all the properties declared in the primary constructor with the following functions.
Also, the copy function is automatically generated. It can be copied while changing any property.
fun moveTo(point: Point, newX: Int): Point {
return point.copy(x = newX)
}
While declaring all properties with val and making the class Immutable, You can easily generate a copy with rewritten values.
The sealed class is a class that can only be inherited within the same file.
sealed class Animal {
}
class Dog: Animal() {
}
class Cat: Animal() {
}
fun greet(animal: Animal) = when(animal) {
is Dog -> "bow wow"
is Cat -> "meow meow"
// else ->No need for else case!
}
Notice when in the greet function above. There is no else case. This is the effect of the sealed class.
In Java, when defining a class inside a class, the meaning changes depending on whether or not the static modifier is added. Let's compare it with Kotlin's description method.
Java | Kotlin |
---|---|
static class A | class A |
class A | inner class A |
Kotlin defaults
It is synonymous with Java's nested class with static
.
Kotlin properties can be declared on one line, Getters and setters can be customized respectively.
class Dog(name: String) {
var name: String = name
get() { //Custom getter
//Field variables are available in getters
//This getter is in name"Chan"Return with
return field + "Chan"
}
set(value) { //Custom setter
//The setter specifies the argument name
//This setter removes whitespace from the front of the name and sets it in the field
field = value.trimMargin()
}
}
Kotlin classes are non-inheritable by default. There is a mechanism to extend the function without inheritance.
With an interface called Movable I have defined a MovableImpl class that implements Movable.
interface Movable {
fun walk()
fun run()
fun currentCount(): Int
}
class MovableImpl: Movable {
private var count: Int = 0
override fun walk() {
this.count += 1
}
override fun run() {
this.count += 3
}
override fun currentCount(): Int = this.count
}
Define a Dog class that extends the functionality of this Movable.
class Dog(movable: MovableImpl): Movable by movable {
}
Following the by
keyword, specify the instance to which you want to delegate Movable functionality.
This Dog class has no implementation for the Movable interface,
It is automatically delegated to MovableImpl.
val dog = Dog(MovableImpl())
dog.walk()
dog.walk()
dog.run()
println(dog.currentCount()) // 5
You can delegate the behavior of property getters and setters. Define a class like this.
class Dog {
var name: String by NameFormatter()
}
class Cat {
var name: String by NameFormatter()
}
Both the Dog and Cat classes have a property called name.
Both specify by
followed by NameFormatter.
Try running the code below.
val dog = Dog()
dog.name = "Pochi"
println(dog.name) //Pochi-chan
val cat = Cat()
cat.name = "Marble"
println(cat.name) //Tama-chan
In both cases, whitespace is removed from the character string assigned to name, and In the getter, "chan" is added as a suffix.
Now let's take a look at the implementation of NameFormatter.
class NameFormatter {
private var name: String = ""
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return this.name + "Chan"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
this.name = value.trimStart()
}
}
Implement the getValue
and setValue
methods following the ʻoperator` keyword.
In this way, property behavior can be delegated to the outside world.
Recommended Posts