λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Kotlin

Kotlin_상속 / 객체 / μΈν„°νŽ˜μ΄μŠ€μ™€ 좔상 클래슀

by λ„μΊλ¦¬πŸ± 2021. 7. 2.
λ°˜μ‘ν˜•

 


상속

 

public : μ½”ν‹€λ¦°μ—μ„œ 속성과 ν•¨μˆ˜κ°€ 기본적으둜 κ°–λŠ” κ°€μ‹œμ„±

private : 속성과 ν•¨μˆ˜κ°€ μ •μ˜λœ 클래슀 λ‚΄λΆ€μ—μ„œλ§Œ μ‚¬μš©λ  수 μžˆλ‹€.

protected : 이 κ°€μ‹œμ„±μ΄ μ§€μ •λœ 속성과 ν•¨μˆ˜λŠ” μžμ‹ μ΄ μ •μ˜λœ 클래슀 λ‚΄λΆ€ λ˜λŠ” 이 클래슀의 μ–΄λ–€ μ„œλΈŒ ν΄λž˜μŠ€μ—μ„œλ„ μ‚¬μš© κ°€λŠ₯

 

is μ—°μ‚°μž : ν˜„μž¬ 객체가 νŠΉμ • νƒ€μž…μΈμ§€ κ²€μ‚¬ν•œλ‹€.

 

 

상속


open class Room(val name: String){

    protected open val dangerLevel : Int = (1..10).shuffled().last()

    fun description() = "Room: ${name}\n" + "μœ„ν—˜ μˆ˜μ€€ : ${dangerLevel}"

    open fun load() = "아무도 여기에 μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.."

    // any νƒ€μž…μ˜ toString을 μ˜€λ²„λΌμ΄λ“œ
    override fun toString(): String {
        return this.name
    }
}

// 상속 받을 땐, : 뒀에 슈퍼 클래슀인 Roomκ³Ό μƒμ„±μž ν˜ΈμΆœμ„ 지정해야 ν•œλ‹€.
// μ„œλΈŒ 클래슀의 μ˜€λ²„λΌμ΄λ”© ν•¨μˆ˜λ‚˜ 속성은 기본적으둜 open이 λ˜μ–΄μ„œ μ„œλΈŒ 클래슀의 μ„œλΈŒ ν΄λž˜μŠ€μ—μ„œλŠ” μ–Έμ œλ“  μ˜€λ²„λΌμ΄λ”© ν•  수 μžˆλ‹€.
open class TownSquare : Room("Town Square")
{
    override val dangerLevel = super.dangerLevel -3
    private val bellSound = "λŒ•λŒ•"

    // Room의 μ„œλΈŒ 클래슀인 TownSquare둜 λΆ€ν„° 또 λ‹€μ‹œ μ„œλΈŒ 클래슀λ₯Ό μƒμ„±ν• μˆ˜ 있게 ν•˜λ˜, TownSquare의 load ν•¨μˆ˜λ₯Ό μ˜€λ²„λΌμ΄λ”© λ˜μ§€ μ•Šκ²Œ ν•˜λ €λ©΄, final!
    final override fun load() = "μ—¬κΈ°λŠ” TownSquare"


    private fun ringBell() = "λ‹Ήμ‹ μ˜ 도착을 μ’…νƒ‘μ—μ„œ μ•Œλ¦½λ‹ˆλ‹€. $bellSound"
}

// is μ—°μ‚°μž - νƒ€μž… μ–΄λ–€ 건지
// any νƒ€μž… - λͺ¨λ“  null λΆˆκ°€λŠ₯ νƒ€μž…μ˜ μ΅œμƒμ˜ 슈퍼 클래슀
//fun printIsSourceOfBlessing(any : Any){
//    val isSourceOfBlessiongs = if(any is Player){
//        any.isBlessed
//    }else{
//        (any as Room).name == "Fount of Blessings"
//    }
//}




fun main() {
    var currentRoom = Room("Foyer")
    println(currentRoom.description())
    println(currentRoom.load())

    var currentTownSquare = TownSquare()
    println(currentTownSquare.description())
    println(currentTownSquare.load())

}

 

 

μ½”ν‹€λ¦° νƒ€μž…μ˜ 상속 계측

- μ½”ν‹€λ¦°μ˜ λͺ¨λ“  Null λΆˆκ°€λŠ₯ ν΄λž˜μŠ€λŠ” μžλ™μœΌλ‘œ AnyλΌλŠ” μ΅œμƒμœ„ 슈퍼 클래슀둜 λΆ€ν„° 상속 λ°›λŠ”λ‹€.

μ½”ν‹€λ¦°μ˜ λͺ¨λ“  κ°μ²΄λŠ” Any의 μ„œλΈŒ 클래슀 μΈμŠ€ν„΄μŠ€ → μ–΄λ–€ νƒ€μž…μ˜ μΈμžλ„ printIsSourceOfBlessings ν•¨μˆ˜μ— 전달할 수 μžˆλ‹€. 

Any

- equals, hashCode,toString μ •μ˜ν•˜κ³  있음 (μΆ”κ°€λ‘œ ν™•μž₯된 속성과 ν•¨μˆ˜λ„ κ°–κ³  μžˆλ‹€.)


✲ μ§€κΈˆκΉŒμ§€ 처럼, AnyλŠ” null λΆˆκ°€λŠ₯ νƒ€μž…μ΄κ³ , Any?λŠ” null κ°€λŠ₯ νƒ€μž…λ‹ˆλ‹€.

νƒ€μž… λ³€ν™˜

 

>> 코틀린을 μ‚¬μš©ν•˜λ©΄ μ„œλ‘œ λ‹€λ₯Έ ν”Œλž«νΌ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€ 수 μžˆλ‹€. 

      μ—¬λŸ¬ 운영체제 JVMμ—μ„œ μ‹€ν–‰λ˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ / JVM 없이 μ‹€ν–‰λ˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ / μ›Ή λΈŒλΌμš°μ €μ—μ„œ μ‹€ν–‰λ˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ/ μ„œλ²„μ— μ„œ μ‹€ν–‰λ˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ / μ„œλ²„μ—μ„œ μ‹€ν–‰λ˜λŠ” Http μ„œλΈ”λ¦Ώ / ꡬ글 μ•ˆλ“œλ‘œμ΄λ“œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜.

>> Any ν΄λž˜μŠ€λŠ” 그런 λ‹€μ–‘ν•œ ν”Œλž«νΌμ— 독립적인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ 생성할 수 있게 ν•΄μ€€λ‹€.


객체 Object

https://www.youtube.com/watch?v=QPqzmKu0Y_k

 

- 해체 μ„ μ–Έ

- 데이터 클래슀 (data class)

- enum 클래슀 

- μ—°μ‚°μž μ˜€λ²„λ‘œλ”©

 

/**
 *
 * Object ν‚€μ›Œλ“œ
 *
 * ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λŠ” λ‚΄λ‚΄ μˆ˜μ‹œλ‘œ λ³€ν•˜λŠ” μƒνƒœ 정보λ₯Ό μ§€μ†μ μœΌλ‘œ μœ μ§€ 관리할 ν•„μš”κ°€ μžˆλ‹€λ©΄ 싱글톀 μ‚¬μš©μ„ κ³ λ €ν•˜μž (예λ₯Ό λ“€λ©΄ Game 클래슀 같은)
 * 싱글톀은 ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€(객체)만 μƒμ„±λ˜λŠ” 것을 λ§ν•œλ‹€.
 * μ½”ν‹€λ¦°μ—μ„œλŠ” object ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬, 싱극톀 객체λ₯Ό μ •μ˜ν•  수 μžˆλ‹€.
 *
 * 싱글톀 κ°μ²΄λŠ” 졜초 μ‚¬μš©μ‹œμ μ— ν•˜λ‚˜λ§Œ μƒμ„±λ˜μ–΄, ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λŠ” λ™μ•ˆ 계속 μœ μ§€λœλ‹€.
 * β˜… 싱글톀은 μ‹œμŠ€ν…œμ˜ μžμ› μ‚¬μš©κ³Ό 뢀담을 μ€„κΈ°μ˜€ 객체λ₯Ό κ³΅μœ ν•  수 μžˆλ‹€λŠ” μž₯점 있음
 * β˜… 닀쀑 μŠ€λ ˆλ“œλ‘œ 싀행될 λ•ŒλŠ” λ°˜λ“œμ‹œ ν•˜λ‚˜μ˜ 객체만 μƒμ„±λ˜λ„λ‘ 동기화 처리λ₯Ό ν•΄μ£Όμ–΄μ•Ό 함
 *
 * Object ν‚€μ›Œλ“œ μ‚¬μš©ν•˜λŠ” 방법 3가지
 * 1. 객체 μ„ μ–Έ 2. 객체 ν‘œν˜„μ‹ 3. λ™λ°˜ 객체
 *
 * Observer
 * ν•¨μˆ˜λ‘œ 직접 μš”μ²­ μ•ˆν–ˆμ§€λ§Œ μ‹œμŠ€ν…œ ν˜Ήμ€ 루틴에 μ˜ν•΄ λ™μž‘ν•˜λŠ” 것을 이벀트라고 λΆ€λ₯΄λ©° 이 이벀트 λ°œμƒμ‹œλ§ˆλ‹€
 * μ¦‰κ°μ μœΌλ‘œ μ²˜λ¦¬ν•˜λ„λ‘ λ§Œλ“œλŠ” νŒ¨ν„΄μ„ μ˜λ―Έν•œλ‹€.
 * > 이벀트λ₯Ό μˆ˜μ‹ ν•˜λŠ” 클래슀
 * > 이벀트의 λ°œμƒ 및 전달 클래슀
 * > 콜백 - 이벀트λ₯Ό λ„˜κ²¨ μ£ΌλŠ” 것을 μ˜λ―Έν•œλ‹€.
 *
 *
 * 데이터 클래슀
 * : 데이터λ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•΄ νŠΉλ³„νžˆ μ„€κ³„λœ 클래슀
 * : κ°•λ ₯ν•œ 데이터 처리 κΈ°λŠ₯을 가짐!
 * 데이터 ν΄λž˜μŠ€λŠ” class ν‚€μ›Œλ“œ μ•žμ— data ν‚€μ›Œλ“œλ₯Ό μΆ”κ°€ν•˜μ—¬ μ •μ˜.
 *
 *
 * μ—°μ‚°μž μ˜€λ²„λ‘œλ”©
 *
 *
 * */


fun main() {
    Game.play()
}

// 1. 객체 μ„ μ–Έ - μƒνƒœ 관리에 μœ μš©ν•¨. ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λŠ” λ™μ•ˆ μ§€μ†μ μœΌλ‘œ μ–΄λ–€ μƒνƒœ 정보λ₯Ό μœ μ§€ 관리할 ν•„μš” μžˆμ„ λ•Œ 특히
// μ΄ˆκΈ°ν™” 블둝이 포함 될수 μžˆλ‹€. - 졜초둜 μ‚¬μš©λ˜λŠ” μ‹œμ μ— ν•˜λ‚˜μ˜ 객체가 μžλ™ μƒμ„±λ˜μ–΄ μ΄ˆκΈ°ν™” 되기 λ•Œλ¬Έ. >> 객체 μƒμ„±μ‹œ μ‹€ν–‰ ν•„μš” μžˆλŠ” μ½”λ“œ 포함해야함
// μƒμ„±μžλŠ” κ°€μ§ˆ 수 μ—†λ‹€.
// 객체 선언에도 일반 클래슀 처럼 속성과 ν•¨μˆ˜κ°€ 포함될 수 μžˆλ‹€.
// κ²Œμž„ 둜직 처리 μ½”λ“œ , κ²Œμž„ 루프, player, room μΈμŠ€ν„΄μŠ€ μƒμ„±ν•˜ν•˜λŠ” 것을 Game 객체 μ•ˆμ— 두어야 ν•œλ‹€.
// ↓ λͺ¨λ“  κ²Œμž„ 둜직이 포함될 것이닀.

object Game{

    private val player = Player("Carrie")
    private var currentRoom: Room = TownSquare()


    // 쀑첩 클래슀 - Game κ°μ²΄μ—μ„œλ§Œ ν•„μš”ν•˜κ³  λ‹€λ₯Έ μ½”λ“œμ—μ„œλŠ” μ‚¬μš©ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 쀑첩 μ‹œν‚΄
      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() = "μ ν•©ν•˜μ§€ μ•Šμ€ λͺ…λ Ήμž…λ‹ˆλ‹€ !"
        }

        init{
            println("방문을 ν™˜μ˜ν•©λ‹ˆλ‹€.")
            player.castFireball(10)
        }

        fun play()
        {
            while(true){
                // κ²Œμž„ μ‹œμž‘
                println(currentRoom.description())
                println(currentRoom.load())

                printPlayerStatus(player)

                print("> λͺ…령을 μž…λ ₯ν•˜μ„Έμš” : ")
                println("졜근 λͺ…λ Ή : ${readLine()}")
            }
        }

        private fun printPlayerStatus(player: Player){
            println("player's name is ${player.nick}")
        }
}

// 2. object ν‚€μ›Œλ“œλ‘œ μ •μ˜λœ 것이 객체 ν‘œν˜„μ‹μ΄λ©°,
// {} μ•ˆμ— μ •μ˜λœ μ½”λ“œκ°€ 읡λͺ… 클래슀의 λͺΈμ²΄λ₯Ό μ •μ˜ν•œ 것.
// 이 읡λͺ… 클래슀의 μΈμŠ€ν„΄μŠ€λŠ” μœ„μ˜ μ½”λ“œκ°€ 싀행될 λ•Œ 생성과 μ΄ˆκΈ°ν™”λœλ‹€.
val abandondedTownSquare = object : Room("room name") {
    override fun load() = "μ˜€μž‰?"
}

// 3. λ™λ°˜κ°μ²΄
// 객체 μ„ μ–Έκ³Ό μœ μ‚¬ ν•˜λ‚˜, μ΅œμƒμ˜ μˆ˜μ€€μ—μ„œ μ‚¬μš© X, 클래슀 내뢀에 μ •μ˜ν•˜μ—¬ μ‚¬μš©
//


// data class
// * 데이터 클래슀
// * : 데이터λ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•΄ νŠΉλ³„νžˆ μ„€κ³„λœ 클래슀
// * : κ°•λ ₯ν•œ 데이터 처리 κΈ°λŠ₯을 가짐!
// * 데이터 ν΄λž˜μŠ€λŠ” class ν‚€μ›Œλ“œ μ•žμ— data ν‚€μ›Œλ“œλ₯Ό μΆ”κ°€ν•˜μ—¬ μ •μ˜.

// 데이터 클래슀λ₯Ό μ •μ˜ν•˜λ©΄, 이 클래슀의 속성에 맞게 μ²˜λ¦¬λ˜λŠ” toString, equals, hashCode ν•¨μˆ˜λ“€μ„ μ½”ν‹€λ¦° μ»΄νŒŒμΌλŸ¬κ°€ μžλ™μœΌλ‘œ μƒμ„±ν•΄μ€Œ.
// μžλ™ μƒμ„±λ˜λŠ” ν•¨μˆ˜λ“€μ΄ 데이터 클래슀의 λͺ¨λ“  속성을 μ²˜λ¦¬ν•  수 있게 ν•˜λ €λ©΄ λ°˜λ“œμ‹œ κΈ°λ³Έ μƒμ„±μžμ— 속성듀을 지정해야 함.
data class Coordinate(val x:Int, val y: Int){
    val isInBounds = x>=0 && y>=0

    operator fun plus(other: Coordinate) = Coordinate(x + other.x , y + other.y)
}


// 해체 μ„ μ–Έ

// enum Class
// μ½”ν‹€λ¦°μ—μ„œλŠ” enum ν΄λž˜μŠ€κ°€ 각 ν•­λͺ©μ— λŒ€ν•΄
// λ‚΄λΆ€μ μœΌλ‘œ name(ν•­λͺ© 이름, string νƒ€μž…) κ³Ό ordinal(ν•­λͺ© μœ„μΉ˜, Int νƒ€μž…) 속성을 κ°–λŠ”λ‹€.
//
enum class Direction(private val coordinate: Coordinate){
    NORTH(Coordinate(0,-1)),
    EAST(Coordinate(1,0)),
    SOUTH(Coordinate(0,1)),
    WEST(Coordinate(-1,0)) ; // 제일 끝에 μ„Έλ―Έ 콜둠!

    fun updateCoordinate(playerCoordinate: Coordinate) =
//        Coordinate(playerCoordinate.x +coordinate.x,
//        playerCoordinate.y +coordinate.y)
        coordinate + playerCoordinate

}

fun getDirectionName(direction: Direction) =
    when(direction){
        Direction.NORTH -> "뢁"
        Direction.EAST -> "동"
        Direction.SOUTH -> "남"
        Direction.WEST -> "μ„œ"

    }

μΈν„°νŽ˜μ΄μŠ€μ™€ 좔상 클래슀

↓ μ•„λž˜ 유튜브 링크 μ΄ν•΄ν•˜κΈ° 맀우 쉽닀!

https://mond-al.github.io/kotlin-visibility-internal.html

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim-indent.html

https://www.youtube.com/watch?v=UpJ5r67oDfY&list=PLg3A12oL1JCNnsU2qTQGDJelJwu4pruji&index=3 

 

import javax.print.DocFlavor

/**
 *
 *
 * μΈν„°νŽ˜μ΄μŠ€(abstract 보닀 μ’€ 더 좔상) == κ·œμΉ™ / κ·œμ•½
 * >> μžλ°”λ‚˜ 코틀린은 닀쀑 상속 μ•ˆλ˜λŠ”λ°, κΈ°λŠ₯을 λ¬΄ν•œμ •μœΌλ‘œ 늘렀갈 수 있음
 * >> μΆ”μƒν΄λž˜μŠ€λŠ” μƒμ„±μžκ°€ μžˆμ§€λ§Œ, μΈν„°νŽ˜μ΄μŠ€λŠ” μƒμ„±μžκ°€ μ—†λ‹€.
 *  좔상화 λ©”μ†Œλ“œμž„μ—λ„ , abstract, open 등이 λͺ¨λ‘ μƒλž΅λ˜μ–΄μžˆμŒ
 *  β˜… μƒμ„±μž μžμ²΄κ°€ μ—†μœΌλ‹ˆκΉŒ μƒμ„±μž 호좜이 μ—†κ³ , μΈμŠ€ν„°μŠ€ 생성 μžμ²΄κ°€ μ•ˆλ¨( 좔상 ν΄λž˜μŠ€λŠ” μƒμ„±μžλŠ” μžˆμ§€λ§Œ 좔상 λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜λΌλ„ ꡬ체화 ν•˜μ§€ μ•ŠμœΌλ©΄, μƒμ„±μžκ°€ λΆˆλ €μ§€μ§€λŠ” μ•ŠμŒ == μΈμŠ€ν„΄μŠ€ν™” λ˜μ§€ λͺ»ν•¨)
 *
 *
 * Abstract μΆ”μƒν΄λž˜μŠ€ - 좔상 λ©”μ†Œλ“œ : λ…Έλ°”λ””
 * 좔상 클래슀의 μΈμŠ€ν„΄μŠ€λŠ” 생성할 수 μ—†μŒ.
 *
 * ꡬ체화/ 좔상화
 * >> Red μ—μ„œ Flock 으둜 κ°€λŠ” μ •λ„λŠ” 좔상화 된 것
 * >> Flock μ—μ„œ Red둜 κ°€λŠ” μ •λ„λŠ” ꡬ체화 된 것
 * */

// μƒˆμ΄μœ„μ— μ˜¬λ €μ§„λ‹€. 고무쀄을 λ‹ΉκΈ΄λ‹€. λ°œμ‚¬λ˜μ–΄ λ‚ μ•„κ°„λ‹€.
// μž₯애물에 λΆ€λ”ͺν˜€ 좩격을 μ£Όλ‹€. 비행을 λ§ˆμΉ˜λ‹€.

// μƒˆ : 이름 , 곡격λ ₯, 곡격λ ₯ κ°€μ€‘μΉ˜ , μƒνƒœ, 컬러
// >> RED λ₯Ό 잘 섀계 ν•΄μ„œ λ‹€λ₯Έ μƒ‰μ˜ μƒˆλ“€μ„ νŒŒμƒ μ‹œν‚¬ κ±°μž„

enum class Color(val hexColor: String)
{
    RED("FF0000"), GREEN("00FF00"), BLUE("0000FF"),
    BLACK("000000"), YELLOW("FFFF00"), WHITE("FFFFFF")
}

enum class Status(val exp: String)
{
    NONE("λΉ„ν–‰ μ‹œμž‘ μ „μ˜"), READY("μƒˆμ΄ μœ„μ— μ€€λΉ„λœ"), SHOT("λ°œμ‚¬λœ"),
    FLYING("λ‚ μ•„κ°€λŠ”"),CRASHED("μΆ©λŒν•œ"), END("비행을 μ™„λ£Œν•œ")
}

// 고무쀄 인자 LENGTH
private val LENGTH = 20

 /**
  * class Red λ₯Ό Flock(κ°€κΈˆλ₯˜) 둜 바꿔야함 (κ³΅ν†΅μ μœΌλ‘œ μ“°λ €κ³ )
 2가지 ν•¨μˆ˜λŠ” μƒˆλ§ˆλ‹€ 달라져야 ν•œλ‹€. "좔상화 ν•¨μˆ˜" abstract - λ°”λ”” μ—†μŒ
 abstract μ•„λ‹Œκ±΄, concrete ν•¨μˆ˜. ꡬ체화 ν•¨μˆ˜λΌκ³  말함.
 β˜… 좔상화 λ©”μ†Œλ“œ(코딩이 μ™„λ£Œ λ˜μ§€ μ•Šμ€)  κ°–λŠ”λ‹€λ©΄ ν•΄λ‹Ή ν΄λž˜μŠ€κ°€ 좔상화 ν΄λž˜μŠ€κ°€ λ˜μ–΄μ•Ό ν•œλ‹€. → λ‚˜λŠ” ν˜„μž¬ 좔상화 λ©”μ†Œλ“œκ°€ 있기 λ•Œλ¬Έμ— μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€ 수 μ—†λ‹€~
  */
abstract class Flock {
    lateinit var name: String // λ‚˜μ€‘μ— setter둜 μ„€μ •ν•  수 μžˆκ²Œλ” lateinit μ‚¬μš© λ˜μ–΄ μžˆλ‹€.
    open val color: Color = Color.RED // override ν•  수 μžˆκ²Œλ” open
    var power: Double = 10.0
    open val weight: Double = 1.1 // κ°€μ€‘μΉ˜
    var status: Status = Status.NONE
    open val type: String = "Red" // μ‹ κ·œ μΆ”κ°€ ν”„λŸ¬νΌν‹°


    // 2μ°¨ μƒμ„±μž - μžμ‹ μ˜ 이름 ν‘œμ‹œ
//    constructor(name: String): this(){
//        this.name = name
//    }

    // Any νƒ€μž…ν•œν…Œ λ¬Όλ € 받은 κ±Έ 재 μ •μ˜ toString
    override fun toString(): String {
        // exp : status enum의 ν”„λ‘œνΌν‹°
        return "${status.exp} ${name} ${type}μƒˆ (power = ${power}, weight = ${weight})"
    }

     // concrete ꡬ체화 ν•¨μˆ˜. 상속을 μƒκ°ν•΄μ„œ private → protected 둜 λ°”κΏ”μ€˜μ•Ό 함.
     protected fun getRandom(max : Int = 10) = (Math.random()*max).toInt() + 1
     protected fun getDamage() = power * weight * getRandom()

    // μƒˆμ΄μœ„μ— μ˜¬λ €μ§€λ‹€.
    fun readyForShoot()
    {
        // μ•„λž˜ this : 자기 μžμ‹ , toString μžλ™ 호좜 λ˜μ–΄ μœ„μ˜ return κ°’ λ‚˜μ˜¬ κ²ƒμž„
        println("step1: ${this}κ°€ μƒˆμ΄ μœ„μ— μ˜¬λ €μ§€λ‹€.")
        // μƒνƒœ λ°”κΏ”μ£ΌκΈ°
        this.status = Status.READY
    }

    // 고무쀄을 λ‹ΉκΈ°λ‹€.
    fun adjustAngleLength(){
        println("step1: ${this}κ°€ 고무쀄이 당겨저 λ°œμ‚¬λ˜λ‹€.")
        this.power += getRandom(LENGTH) *this.weight
        println("\t >> κ²°μ •λœ power: ${power}")
        this.status = Status.SHOT
    }

    // λ°œμ‚¬λ˜μ–΄ λ‚ μ•„κ°€λ‹€. → abstract : λ°”λ”” μ—†κ²Œ - λ‹€λ₯Έ Red λ‚˜ Blue μ—μ„œ μ˜€λ²„λΌμ΄λ“œν•΄μ„œ μ“°κ²Œλ” μœ λ„ ν•˜κ³  μžˆλ‹€.
    abstract fun flyAtterShoot()
//    {
//        println("step3: ${this}κ°€ κ³΅μ€‘μœΌλ‘œ λ‚ μ•„κ°€λ‹€.")
//        this.status = Status.FLYING
//    }

    // μž₯애물에 λΆ€λ”ͺν˜€ 좩격을 μ£Όλ‹€. → abstract : λ°”λ”” μ—†κ²Œ
    abstract fun crashWithDamage()
//    {
//        println("step 4: ${this}κ°€ μž₯애물에 λΆ€λ”ͺν˜€ 좩격을 μ£Όλ‹€.")
//        println("\t >> μž…νžŒ 총 λŒ€λ―Έμ§€ : ${java.lang.String.format("%.2f", getDamage())} 점")
//        this.status = Status.CRASHED
//    }

    // 비행을 λ§ˆμΉ˜λ‹€.
    fun landingForEnd()
    {
        println("step5: ${this}κ°€ 비행을 λ§ˆμΉ˜λ‹€.")
        println("-".repeat(80)+"\n")
        this.status = Status.END
    }
}


// 좔상화 λ©”μ†Œλ“œμž„μ—λ„ , abstract, open 등이 λͺ¨λ‘ μƒλž΅λ˜μ–΄μžˆμŒ
// μ‚¬μš©ν•  λ–„μ—λŠ” override λ₯Ό 톡해 μ‚¬μš© ν•˜λ©΄ 됨.
interface Spliter {

    fun splitBirds()
    fun splitDamage(vararg birds: String)


}

// μ•ˆμ— 3마리둜 λΆ„λ¦¬λ˜λŠ” κ³ μœ ν•œ κΈ°λŠ₯을 λ‹΄κ³  μžˆλ‹€.
class Blues(_name:String): Flock(),Spliter
{

    init {
        super.name = _name
        super.power = 8.0
        status  = Status.NONE

//        color = Color.BLUE  // err - val μ΄λ‹ˆκΉŒ λ³€κ²½ μ•ˆλ˜μ§€λ§Œ, Flock ν΄λž˜μŠ€μ—μ„œ 상속 κ°€λŠ₯ν•˜κ²Œ ν•΄λ‘μ—ˆκΈ° 떄문에
//        weight = 1.3 // err
    }

    override val color: Color = Color.BLUE

    override val type: String = "Blues"

    override val weight: Double = 1.3

    // μžμ‹ λ§Œμ˜ κΈ°λŠ₯이 있음 - 3마리둜 split 됨.
    // μž¬μ •μ˜ Spliiter μΈν„°νŽ˜μ΄μŠ€ ν†΅ν•΄μ„œ 옴
    override fun splitBirds()
    {
        println("\t>> 짐, 제이크, 제이 μ„Έλ§ˆλ¦¬ μƒˆλ“€λ‘œ 뢄리 λ˜μ–΄ λ‚ μ•„κ°„λ‹€.")
    }

    override fun splitDamage(vararg birds: String)
    {
        for (bird in birds){
            println("\t>> '${bird}'κΈ° μž₯애물에 λΆ€λ”ͺν˜€ 좩격을 μ£Όλ‹€.")
            println("\t>> μž…νžŒ 총 λŒ€λ―Έμ§€: ${java.lang.String.format("%.2f",getDamage())}' 점")

        }
    }


    // Flock 클래슀둜 λΆ€ν„° μ˜€λ²„λΌμ΄λ“œ
    override fun flyAtterShoot() {
        println("step3 : ${this}κ°€ κ³΅μ€‘μœΌλ‘œ λ‚ μ•„κ°€λ‹€.")
        splitBirds()
        this.status = Status.FLYING
    }

    override fun crashWithDamage() {
        println("step4: ${this}κ°€ μž₯애물에 λΆ€λ”ͺν˜€ 좩격을 μ£Όλ‹€.")
        splitDamage("Jim Blueμƒˆ", "Jake Blueμƒˆ", "Jay Blueμƒˆ")
        println("\t>> μž…νžŒ 총 λŒ€λ―Έμ§€: ${java.lang.String.format("%.2f",getDamage())}' 점")
        this.status = Status.CRASHED
    }

}


/** 상속 λ°›μž!
상속 받은 ν΄λž˜μŠ€μ— μžˆλŠ” 것은 μ—†μ• μž~
 */
 class Red(_name: String): Flock() {

    init {
        super.name = _name
    }

    /** μž¬μ •μ˜! 해야함 - λ°˜λ“œμ‹œ!! implement ovveride */
    override fun flyAtterShoot()
    {
        println("step3: ${this}κ°€ κ³΅μ€‘μœΌλ‘œ λ‚ μ•„κ°€λ‹€.")
        this.status = Status.FLYING
    }

    // μž₯애물에 λΆ€λ”ͺν˜€ 좩격을 μ£Όλ‹€. → abstract : λ°”λ”” μ—†κ²Œ
    override fun crashWithDamage()
    {
        println("step 4: ${this}κ°€ μž₯애물에 λΆ€λ”ͺν˜€ 좩격을 μ£Όλ‹€.")
        println("\t >> μž…νžŒ 총 λŒ€λ―Έμ§€ : ${java.lang.String.format("%.2f", getDamage())} 점")
        this.status = Status.CRASHED
    }


}
fun main() {
//    val bird1 = Red()
//    bird1.name = "λ ˆλ“œ1" // lateinit을 μ‚¬μš©ν•΄μ„œ

//    val bird1 = Red("μ§€μ˜")
//    println("bird1 = ${bird1}")
//    bird1.readyForShoot()
//    bird1.adjustAngleLength()
//    bird1.flyAtterShoot()
//    bird1.crashWithDamage()
//    bird1.landingForEnd()
//
//    println()
//    listOf<Red> (Red("길동"),Red("영희"),Red("κΊ½μ •")).forEach {
//        it.readyForShoot()
//        it.adjustAngleLength()
//        it.flyAtterShoot()
//        it.crashWithDamage()
//        it.landingForEnd()
//    }

    println()
    listOf<Blues> (Blues("철수"),Blues("μ•ˆλ‚˜"),Blues("λŒ€μ‚°"))
        .forEach {
            with(it) {
                // with ν•¨μˆ˜μ— it을 λ°›μ•„μ„œ 객체가 this λ¬Έλ§₯에 λ“€μ–΄ μ˜¨λ‹€.this λ¬Έλ§₯에 κΉ”λ € 있기 λ•Œλ¬Έμ— μ•„λž˜ it. 을 μƒλž΅ν•œλ‹€.
                readyForShoot()
                adjustAngleLength()
                flyAtterShoot()
                crashWithDamage()
                landingForEnd()
            }
    }
}

 

exitProcess : μ½”ν‹€λ¦° ν‘œμ€€ 라이브러리 ν•¨μˆ˜. ν˜„μž¬ μ‹€ν–‰ 쀑인 JVM μΈμŠ€ν„΄μŠ€(우리 ν”„λ‘œκ·Έλž¨)을 쀑단 μ‹œν‚΄.

import kotlin.system.exitProcess

λ°˜μ‘ν˜•

λŒ“κΈ€