지난 학습 주제는 코틀린 클래스의 상속과 타입이었습니다
아래에 클래스에 관한 지난 학습들의 링크를 걸어놓겠습니다
2020/05/04 - [Android] - [Android] 코틀린(Kotlin) 클래스(Class) 생성과 초기화
2020/05/04 - [Android] - [Android] 코틀린(Kotlin) 클래스(Class)의 상속(Inheritance)와 타입(Type)
이번에도 이어서 다른 타입의 클래스인
중첩 클래스(nested class), 데이터 클래스(data class), 열거 클래스(enum class)와
object 키워드 사용법을 학습하겠습니다
package com.ros.sandbox
import java.io.File
/* object declaration */
object Game {
private val player = Player("GuruSa")
private var currentRoom: Room = TownSquare()
init {
println("Welcome!")
player.castFireball()
}
fun play() {
while(true) {
println(currentRoom.description())
println(currentRoom.load())
printPlayerStatus(player)
print("> Input commend : ")
println(GameInput(readLine()).processCommand())
}
}
private fun printPlayerStatus(player: Player) {
println("(Aura: ${player.auraColor()}) " + "(Blessed: ${if (player.isBlessed) "YES" else "NO"})")
println("${player.name} ${player.formatHealthStatus()}")
}
/* nested class */
private class GameInput(arg: String?) {
private val input = arg ?: ""
val command = input.split(" ")[0]
val argument = input.split(" ").getOrElse(1, { "" })
fun processCommand() = when ( command.toLowerCase() ) {
else -> commandNotFound()
}
private fun commandNotFound() = "This command is not suitable"
}
}
class PremadeWorldMap {
/* companion object */
companion object {
private const val MAPS_FILEPATH = "sandbox.maps"
fun load() = File(MAPS_FILEPATH).readBytes()
}
}
fun main(args: Array<String>) {
Game.play()
/* object expression */
val abandonedTownSquare = object : TownSquare() {
override fun load() = "I expected to be welcomed, but no one here"
}
println(abandonedTownSquare.load())
}
object 키워드는 싱글톤(singleton) 객체를 정의합니다
object 키워드의 사용법은 세 가지가 있는데
객체 선언(object declaration), 객체 표현식(object expression), 동반 객체(companion object)입니다
객체 선언은 최상위와 클래스 내부에서도 사용될 수 있고
둘 다 오직 하나의 객체만 생성됩니다
(여기서는 Game class)
객체 표현식은 익명(anonymous) 클래스이며
만약 함수 내에 포함되어 있다면 여러 개의 인스턴스가 생성됩니다
(여기서는 abandonedTownSquare에 대입됨)
동반 객체는 최상위 수준에서는 사용할 수 없고
클래스 내부에 정의하여 사용할 수 있는데
하나의 클래스에 하나의 동반 객체만 포함될 수 있고
포함 클래스의 인스턴스 수에 관계 없이 하나만 생성됩니다
(여기서는 PremadeworldMap 클래스 내부)
위에서 보면 다른 클래스 내부에 정의되는 모든 클래스가
이름이 없어야되는 것처럼 보이지만 이름이 있는
중첩 클래스(nested class)도 있습니다
(여기서는 GameInput 클래스)
package com.ros.sandbox
/* enum class */
enum class Direction(private val coordinate: Coordinate) {
NORTH(Coordinate(0, -1)),
EAST(Coordinate(1, 0)),
SOUTH(Coordinate(0, 1)),
WEST(Coordinate(-1, 0));
fun getDirectionName(direction: Direction) =
when ( direction ) {
Direction.NORTH -> "NORTH"
Direction.EAST -> "EAST"
Direction.SOUTH -> "SOUTH"
Direction.WEST -> "WEST"
}
fun updateCoordinate(playerCoordinate: Coordinate) =
/*
Coordinate(
playerCoordinate.x + coordinate.x,
playerCoordinate.y + coordinate.y)
*/
coordinate + playerCoordinate
}
/* data class */
data class Coordinate(val x: Int, val y: Int) {
val isInBound = x >= 0 && y >= 0
operator fun plus(other: Coordinate) = Coordinate(x + other.x, y + other.y)
}
/*
class PlayerScore(val experience: Int, val level: Int) {
operator fun component1() = experience
operator fun component2() = level
}
*/
자 이제 위의 코드는 데이터 클래스와 열거형 클래스입니다
데이터 클래스는 비즈니스 로직 처리보다는
데이터값을 저장하는 속성을 갖는 클래스입니다
지난 학습 주제에서 코틀린의 null 불가능 클래스가
Any 클래스로부터 상속받는다고 학습하였습니다
또 Any 클래스에는 toString, equals, hashCode 함수가 있는데
데이터 클래스는 속성의 값이 의미가 있으므로
반드시 이런 함수들이 필요하고 이런 함수들을 자동으로 생성해줍니다
여기에 copy 함수와 해체 선언(destructuring declaration)에 필요한 componentN도 포함됩니다
데이터 클래스는 위와 같은 편리함을 제공하지만
아래와 같은 요구 사항도 존재하는데요
데이터 클래스의 요구 사항 1. 최소한 하나의 매개변수를 갖는 기본 생성자를 가져야 한다 2. 기본 생성자의 매개변수에는 val이나 var이 지정되어야 한다 3. abstract, open, sealed, inner 키워드를 지정할 수 없다 |
열거형 클래스에 대해서는 각 항목의 위치가 0부터 시작된다는 점과
함수 추가를 위해서는 ;(세미콜론)이 항목 끝 지점에 추가되어야 한다는 점
호출할 때는 클래스명.항목명.함수명의 형태라는 점 이정도가 되겠습니다
마지막으로 데이터 클래스 Coordinate를 보시면
plus함수가 오버로딩 되어 있습니다
이는 코틀린의 연산자(operator) +를 오버로딩하는 것입니다
아래는 오버로딩 가능한 연산자 목록입니다
연산자 | 오버로딩 함수명 | 기능 |
+ | plus | 객체를 다른 객체와 더한다 |
+= | plusAssign | 객체를 다른 객체와 더한 후 그 결과를 왼쪽 피연산자 객체에 저장한다 |
== | equals | 두 객체가 같으면 true, 다르면 false |
> | compareTo | 왼쪽 객체가 오른쪽 객체보다 크면 true, 아니면 false |
[] | get | 지정된 인덱스의 컬렉션 요소를 반환한다 |
.. | rangeTo | 범위 객체를 생성한다 |
in | contains | 객체가 컬렉션에 있으면 true를 반환한다 |
이것으로 오늘의 학습을 마치겠습니다
그럼 이만-_-
'Android' 카테고리의 다른 글
[Android] 코틀린(Kotlin) 제네릭(Generic) (0) | 2020.05.17 |
---|---|
[Android] 코틀린(Kotlin) sealed 클래스, 추상클래스, 인터페이스 (0) | 2020.05.08 |
[Android] 코틀린(Kotlin) 클래스(Class)의 상속(Inheritance)와 타입(Type) (0) | 2020.05.04 |
[Android] 코틀린(Kotlin) 클래스(Class) 생성과 초기화 (0) | 2020.05.04 |
[Android] 코틀린(Kotlin) 컬렉션(Collection) (0) | 2020.04.28 |