๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์–ธ์–ด/Kotlin

[Kotlin ๋ฌธ๋ฒ• ์ข…ํ•ฉ] - ์ธํ„ฐํŽ˜์ด์Šค, ์ถ”์ƒ ํด๋ž˜์Šค

by ์ ผ์ ผ39 2024. 3. 5.

 

1. ์ธํ„ฐํŽ˜์ด์Šค

    : ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ๋ณ„๊ฐœ๋กœ ๋‹ค๋ฅธ ๊ทธ๋ฃน๊ณผ ๊ฒน์น˜๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์‹œ ์‚ฌ์šฉ...

    - ๊ทผ๋ณธ์ ์ธ ๊ณตํ†ต์ ์„ ์ƒ์†๋ฐ›๊ณ , ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ๋“ค์€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ถ”๊ฐ€
    - ์ถ”์ƒ๋ฉ”์†Œ๋“œ ์‚ฌ์šฉ ๊ถŒ์žฅ (๊ตฌํ˜„ ์‹œ ์ •์˜, ๊ตฌํ˜„ ํ•„์ˆ˜)

//์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์ค‘๊ตฌํ˜„ ๊ฐ€๋Šฅ, ํด๋ž˜์Šค๋Š” ๋‹ค์ค‘์ƒ์† ๋ถˆ๊ฐ€๋Šฅ
//์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ทธ ์ž์ฒด์˜ ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ ๊ฐ–์ง€ ๋ชปํ•จ
//์ธํ„ฐํŽ˜์ด์Šค : ์ธํ„ฐํŽ˜์ด์Šค ๊ฐ€๋Šฅ 

interface WaterBirdBehavior {
	//๋ณ€์ˆ˜ ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜๋Š” ์—†์Œ. ์ƒ์ˆ˜๋Š” ๊ฐ€์งˆ ์ˆ˜ ์žˆ์–ด๋„
    
    fun swim()
    //์ถ”์ƒ๋ฉ”์†Œ๋“œ ์“ฐ๋Š” ๊ฒŒ ์ข‹์Œ...
//    fun swim() {
//        println("์ˆ˜์˜ ํ•ฉ๋‹ˆ๋‹ค")
//    }
}
fun main() {
    var bird = Bird("์ƒˆ")
    var chicken = Chicken("๋‹ญ")
    var duck = Duck("์˜ค๋ฆฌ")

    bird.fly()
    chicken.fly()
    duck.swim()
}

open class Bird(name:String) {
    var name: String = ""

    init {
        this.name = name
    }

    fun fly() {
        println("${name} ๋‚ ์•„์š”~")
    }
}

class Chicken(name: String) : Bird(name) {}

class Duck(name: String) : Bird(name), WaterBirdBehavior {
    	//java์™€ ๋‹ค๋ฅด๊ฒŒ ํด๋ž˜์Šค ์˜†์— implements ~~ ์•ˆํ•ด๋„ ๋˜๋‚˜๋ด„
        //๊ตฌํ˜„ํ•  ๋•Œ ์ •์˜ ํ•„์ˆ˜, ๊ตฌํ˜„ ํ•„์ˆ˜
    override fun swim() {
        println("${name}๊ฐ€ ์ˆ˜์˜ํ•ด์š”~")
    }
}

//ํ”„๋กœํผํ‹ฐ๋Š” ์˜ค์ง ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋กœ ์„ ์–ธ(abstract ํ‚ค์›Œ๋“œ ์—†์–ด๋„ ์ถ”์ƒ)
        ๋‹จ, val๋กœ ์„ ์–ธ๋œ ํ”„๋กœํผํ‹ฐ๋Š” get() ํ†ตํ•ด ํ•„์š”ํ•œ ๋‚ด์šฉ ๊ตฌํ˜„ ๊ฐ€๋Šฅ, override ์‚ฌ์šฉํ•˜๊ธฐ

interface Pet{
    var category: String
    fun feeding()
    fun patting(){
        println("Keep Patting")
    }
}

class Cat(override var category: String) : Pet{
    override fun feeding(){
        println("Feed the cat a tuna can")
    }
}

fun main(){
    val obj = Cat("small")
    println("Pet Category : ${obj.category}")
    obj.feeding() //๊ตฌํ˜„๋œ ๋ฉ”์„œ๋“œ
    obj.patting() //๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ
}

//Pet Category : small
//Feed the cat a tuna can
//Keep Patting
...
interface Pet{
    var category: String
    val msgTags: String
        get()= "I'm your pet"
    
    fun feeding()
    fun patting(){
        println("Keep patting")
    }
}
...
println("${obj.msgTags}")
...

    - msgTags ์ดˆ๊ธฐํ™”๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ get() ํ†ตํ•ด ๋ฐ˜ํ™˜๊ฐ’์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ(value๋ฅผ ์ €์žฅํ•˜์ง€๋Š” ๋ชปํ•จ)

//๋ฉ”์„œ๋“œ๋Š” ์ถ”์ƒ, ์ผ๋ฐ˜(๊ตฌํ˜„๋ถ€ ํฌํ•จ) ๋ฉ”์„œ๋“œ ๋ชจ๋‘ ๊ฐ€๋Šฅ

//์ธํ„ฐํŽ˜์ด์Šค์™€ ์˜ค๋ฒ„๋กœ๋”ฉ

interface Pet{
    var category: String
    val msgTags: String
        get()= "I'm your pet"
        
    var species: String 	//์ข…์„ ์œ„ํ•œ ํ”„๋กœํผํ‹ฐ
    
    fun feeding()
    fun patting(){
        println("Keep patting")
    }
}

open class Animal(val name: String)

class Dog(name: String, override var category: String) : Animal(name), Pet {

    override var species: String = "dog"

    override fun feeding() {
        println("Feed the dog a bone")
    }
}

class Cat(name: String, override var category: String) : Animal(name), Pet {

    override var species: String = "cat" 	//ํ”„๋กœํผํ‹ฐ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•ด ์ข…์„ ํŠน์ •

    override fun feeding() {
        println("Feed the cat a snack")
    }
}

class Master{

    //species ํ•œ ๋’ค์—๋Š”
    fun playWithPet(pet: Pet){ 	//์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ์ฒด๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •
        println("Enjoy with my ${pet.species}")
    }

    fun playWithPet(dog: Dog){ 		// ์ข…๋ฅ˜์— ๋”ฐ๋ผ ์˜ค๋ฒ„๋กœ๋”ฉ
        println("play with Dog")
    }
    fun playWithPet(cat: Cat){
        println("play with Cat")
    }
}

fun main(){
    val master = Master()
    val dog = Dog("ํƒ„์ด", "small")
    val cat = Cat("๋ฌด", "big")
    master.playWithPet(dog)
    master.playWithPet(cat)
}

    - fun playWithPet(pet: Pet) ๋ถ€๋ถ„์€ ํ•ด๋‹น ๊ฐ์ฒด์˜ ์‹ค์ œ ์œ ํ˜•์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ๊ฒฐ์ •๋จ

 

//์—ฌ๋Ÿฌ๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์•˜๋Š”๋ฐ ์ด๋ฏธ ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” ๋™์ž‘์„ overrideํ•˜๋ ค๊ณ  ํ•จ,
    ๊ทผ๋ฐ ์ด๋ฆ„์ด ์ธํ„ฐํŽ˜์ด์Šค๋ผ๋ฆฌ ๊ฒน์นœ๋‹ค๋ฉด

class ํด๋ž˜์Šค๋ช… : ์ธํŽ˜1, ์ธํŽ˜2{

    override fun jump(){
        super<๊ตฌํ˜„๋œ๋™์ž‘์„ ์ƒ์†๋ฐ›์•„์˜ฌ ์ธํ„ฐํŽ˜์ด์Šค๋ช…>.๋™์ž‘์ด๋ฆ„()
        println("do it")
    }
}

fun main(){
    val ex1 = ํด๋ž˜์Šค๋ช…()
    ex1.jump()
}

 

    //by ๋ฅผ ํ†ตํ•œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ„์ž„

interface A {
    fun functionA()
}

interface B {
    fun functionB()
}

class C(val a: A, val b: B) {
    fun functionC() {
        a.functionA()
        b.functionB()
    }
}

    ^ ์œ„๋Š” functionA(), functionB() ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด a, b ๋ณ€์ˆ˜(๊ฐ๊ฐ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด)๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ

class DelegatedC(a: A, b: B): A by a, B by b{
    fun functionC(){
        functionA()
        functionB()
    }
}

    ^ a, b๋ฅผ ๊ฐ๊ฐ ์ธํ„ฐํŽ˜์ด์Šค A, B์— ์œ„์ž„ํ•ด์„œ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ ์‹œ . ์—†์ด๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋จ

//์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•  ๋•Œ, ๋‹ค๋ฅธ ํด๋ž˜์Šค์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์œ„์ž„ํ•ด ์™€ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

interface Nameable{
    var name: String
    fun fly()
}

class StaffName : Nameable {
    override var name: String = "Sean"
    override fun fly(){
        println("flying")
    }
}

class Work: Runnable{ 		//์Šค๋ ˆ๋“œ ์‹คํ–‰์„ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
    override fun run(){
        println("work...")
    }    
}
//๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜์— ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์œ„์ž„
class Person(name: Nameable, work: Runnable): Nameable by name, Runnable by work

fun main(){
    val person = Person(StaffName(), Work()) //์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ์ฒด ๋ฐ”๋กœ ์ „๋‹ฌ
    println(person.name) 	//์—ฌ๊ธฐ์„œ StaffName ํด๋ž˜์Šค์˜ name์— ์ ‘๊ทผ
    person.run() 		//์—ฌ๊ธฐ์„œ Work ํด๋ž˜์Šค์˜ run ์ ‘๊ทผ
    person.fly()
}

//Sean
//work...
//flying

 

//์ปคํ”ผ๋ฉ”์ด์ปค ์˜ˆ์‹œ

interface Heater{
    fun on()
    fun off()
    fun isHot() : Boolean
}
class ElectricHeater(var heating: Boolean = false) : Heater {
    override fun on() {
        println("[ElectricHeater] heating...")      //5
        heating = true
    }

    override fun off() {
        heating = false
        println("ElectricHeater ํด๋ž˜์Šค์˜ off ํ•จ์ˆ˜")       //9
    }

    override fun isHot() : Boolean {
        println("ElectricHeater ํด๋ž˜์Šค์˜ isHot ํ•จ์ˆ˜")         //6
        return heating
    }
}
interface Pump {
    fun pump()
}
class Thermosiphon(heater: Heater) : Pump, Heater by heater { // ์œ„์ž„์˜ ์‚ฌ์šฉ
    override fun pump() {
        if (isHot()) {
            println("[Thermosiphon] pumping...");       //7
        }
    }
}
interface CoffeeModule {
    fun getThermosiphon() : Thermosiphon
}
class MyDripCoffeeModule : CoffeeModule {
    companion object {
        val electricHeater: ElectricHeater by lazy { // lazy๋ฅผ ์ด์šฉํ•œ ์ง€์—ฐ ์ดˆ๊ธฐํ™” ๊ธฐ๋ฒ• ์‚ฌ์šฉ
            println("MyDripCoffeeModule ํด๋ž˜์Šค์˜ electricHeater ์ƒ์ˆ˜")        //4
            ElectricHeater()
        }
    }

    private val _thermosiphon : Thermosiphon by lazy {
        println("MyDripCoffeeModule ํด๋ž˜์Šค์˜ private _thermosiphon ์ƒ์ˆ˜")         //3
        Thermosiphon(electricHeater)
    }

    override fun getThermosiphon() : Thermosiphon {
        println("MyDripCoffeeModule ํด๋ž˜์Šค์˜ getThermosiphon ํ•จ์ˆ˜")       //2
        return _thermosiphon
    }
}
class CoffeeMaker(val coffeeModule: CoffeeModule) {
    fun brew() {
        val theSiphon: Thermosiphon = coffeeModule.getThermosiphon()
        theSiphon.on()
        theSiphon.pump()
        println("Coffee, here! Enjoy!~")        //8
        theSiphon.off()
    }
}

fun main() {
    val coffeeMaker = CoffeeMaker(MyDripCoffeeModule())     //์—ฌ๊ธฐ์„  ๊ณต๊ฐ„๋งŒ๋“ค๊ธฐ์ธ๋“ฏ
    println("์ˆœ์„œํ™•์ธ")     //1
    coffeeMaker.brew()
}
์ˆœ์„œํ™•์ธ
MyDripCoffeeModule ํด๋ž˜์Šค์˜ getThermosiphon ํ•จ์ˆ˜
MyDripCoffeeModule ํด๋ž˜์Šค์˜ private _thermosiphon ์ƒ์ˆ˜
MyDripCoffeeModule ํด๋ž˜์Šค์˜ electricHeater ์ƒ์ˆ˜
[ElectricHeater] heating...
ElectricHeater ํด๋ž˜์Šค์˜ isHot ํ•จ์ˆ˜
[Thermosiphon] pumping...
Coffee, here! Enjoy!~
ElectricHeater ํด๋ž˜์Šค์˜ off ํ•จ์ˆ˜

 

 

2. ์ถ”์ƒ ํด๋ž˜์Šค

    : ์„ ์–ธ ๋“ฑ์˜ ๋Œ€๋žต์ ์ธ ์„ค๊ณ„ ๋ช…์„ธ, ๊ณตํ†ต์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค

    - ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์ถ”์ƒ ํด๋ž˜์Šค์˜ ๋‚ด์šฉ์„ ๋” ๊ตฌ์ฒดํ™”ํ•ด์•ผ ํ•จ
    - abstract ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ
    - ์ผ๋ฐ˜์ ์ธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ธ์Šคํ„ด์Šคํ™”ํ•  ์ˆ˜ ์—†์Œ
    - ํ•ด๋‹น ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์ ธ์•ผ ํ•˜๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉํ•จ

    - ํด๋ž˜์Šค, ํ”„๋กœํผํ‹ฐ, ๋ฉ”์„œ๋“œ ๋ชจ๋‘ abstract๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Œ (์ดˆ๊ธฐํ™” or ๊ตฌํ˜„์ด ํ•„์š”)

abstract class Printer{
    abstract fun print() 	//์ถ”์ƒ ๋ฉ”์„œ๋“œ
}

val myPrinter = object: Printer(){ 	//๊ฐ์ฒด ์ธ์Šคํ„ด์Šค
    override fun print(){ 	//์ถ”์ƒ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
        println("printing!")
    }
}

fun main(){
    myPrinter.print()
}