Android

[Android] 코틀린(Kotlin) 다른 타입의 클래스(Class)

구루싸 2020. 5. 4. 20:03
반응형
SMALL

지난 학습 주제는 코틀린 클래스의 상속과 타입이었습니다

아래에 클래스에 관한 지난 학습들의 링크를 걸어놓겠습니다

2020/05/04 - [Android] - [Android] 코틀린(Kotlin) 클래스(Class) 생성과 초기화

 

[Android] 코틀린(Kotlin) 클래스(Class) 생성과 초기화

오늘의 학습 주제는 코틀린의 클래스(Class)입니다 클래스하면 떠오르는 것은 객체 지향(object-oriented)인데 워낙에 정보가 많은 부분이기 때문에 설명은 생략하고 바로 코드로 진행해보겠습니다 package com.ro..

yssa.tistory.com

2020/05/04 - [Android] - [Android] 코틀린(Kotlin) 클래스(Class)의 상속(Inheritance)와 타입(Type)

 

[Android] 코틀린(Kotlin) 클래스(Class)의 상속(Inheritance)와 타입(Type)

이번 학습은 지난 학습에 이어 코틀린의 클래스에 대해 학습하겠습니다 지난 학습에 클래스의 생성과 초기화에 대해 알아보았는데요 모르신다면 아래의 링크로↓↓↓ 2020/05/04 - [Android] - [Andro..

yssa.tistory.com

이번에도 이어서 다른 타입의 클래스인

중첩 클래스(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를 반환한다

이것으로 오늘의 학습을 마치겠습니다

그럼 이만-_-

 

 

반응형
LIST