공상하는 개발자

[코틀린] 코틀린 익숙해지기 2탄 (object, inline 함수 등) 본문

개발/코틀린

[코틀린] 코틀린 익숙해지기 2탄 (object, inline 함수 등)

공상과학소설 2020. 3. 5. 16:43
반응형

같은 이름의 함수 식별

같은 이름의 추상 함수가 여러 개 일 때

interface Interface1 {
    fun funcA()
}

interface Interface2 {
    fun funcA()
}

abstract class Parent1 {
    abstract fun funcA()
}

class Child : Parent1(), Interface1, Interface2 {
    override fun funcA() {
        print("Child의 funcA() 호출...")
    }
}

fun main() {
    val obj = Child()
    obj.funcA()	//Child의 funcA() 호출... 출력
}

 

한 번만 정의해줌으로써 사용이 가능하다.

 

같은 이름의 추상 함수, 일반 함수를 사용하는 방법

interface Interface3 {
    fun funcA() {
        println("Interface3의 funcA() 호출....")
    }
}

abstract class Parent2 {
    abstract fun funcA()
}

class Child2 : Parent2(), Interface3 {
    override fun funcA() {
        super.funcA()   //Interface3의 funcA() 호출
        println("Child2의 funcA() 호출....")
    }
}

fun main() {
    val obj = Child2()
    obj.funcA() 
    /*
    Interface3의 funcA() 호출....
    Child2의 funcA() 호출....
    */
}

super를 써주어서 사용할 수 있다.

 

인터페이스에 같은 이름의 일반 함수가 여러 개일 경우에 이용방법

interface Interface4 {
    fun funcA() {
        println("Interface4의 funA()호출......")
    }
}

interface Interface5 {
    fun funcA() {
        println("Interface5의 funcA()호출......")
    }
}

class Child3 : Interface4, Interface5 {
    override fun funcA() {
        super<Interface5>.funcA()
    }

    fun a() {
        super<Interface4>.funcA()
    }
}

fun main() {
    val obj = Child3()
    obj.funcA() //Interface5의 funcA()호출......
    obj.a() //Interface4의 funA()호출......
}

super <인터페이스 이름>. 함수명 형식으로 사용할 수 있다.

 


object 싱글톤  패턴

-> 자바 싱글톤 패턴을 간단하게 object로 해결할 수 있다.

 

object : 프로그램 전체에서 공유 가능한 유일한 객체를 만들 때 사용한다.

 

❗️object로 선언된 객체는 open 키워드를 사용할 수 없다.

 

object Man {
    var name: String = ""
    var age: Int = 0
    fun info() {
        println(name)
        println(age)
    }
}

fun main() {
    //Man 식별자를 이용해서 멤버함수에 바로 접근
    Man.name = "홍길동"
    Man.age = 34
    Man.info()

    val man:Man = Man
    man.info()
}

 

Companion Object (동반자 객체)

코틀린에는 static 키워드가 없고 Companion Object를 이용한다.

동반자 객체는 클래스당 하나만 존재한다.

class Human private constructor() {

    companion object {  //동반자 객체를 선언(자바의 static 키워드를 붙인것과 같다)
        fun create(): Human {
            cnt += 1
            return Human()
        }

        var cnt = 0
            private set //외부에서 cnt 값을 수정 불가!
    }
}

fun main() {
    val aa = Human.create()
    val bb = Human.create()

    println(Human.cnt)    //2 출력
    //cnt 를 공유하기 때문에
}

 

※Companion Object의 확장 함수

-> 동반자 객체는 클래스 이름만으로 접근 가능하지만 확장 함수에서는 클래스 이름만 적을 경우 동반자 객체가 아닌 클래스 자체의 멤버함       수로 추가되기 때문에 반드시 Companion 키워드를 사용해야 한다.

 

형식 : fun 클래스 이름. Companion. 함수 이름() {}

 

class Aaa {
    companion object
}

fun Aaa.Companion.a() = Aaa()	//동반자 객체에 a() 함수를 주입

fun main() {
    val obj = Aaa.a()	//Aaa의 동반자 객체에 있는 a()함수를 호출
    //호출할 때는 Companion 생략 가능
}

 

인라인 함수

-> 함수 호출 문이 함수 속에 들어 있는 코드로 대체되는 것을 의미한다.

    인라인 함수는 실행 흐름의 이동을 없을 수 있으므로 성능을 개선할 수 있다.

 

✔️인라인 함수 선언은 inline 키워드를 이용한다.

 

❗️함수 안에 코드의 내용이 많은 경우는 효율성이 떨어질 수 있으므로 인라인 함수를 사용하는 것은 바람직하지 않다.

❗️인라인 함수는 주로 함수 안에 코드가 적고 빈번하게 호출되는 함수에만 적용하는 것이 바람직하다.

 

inline fun myFunc(){
    println("myFunc 호출...")
    println("두번째 myFunc 호출...")
}

fun main() {
    myFunc()
    myFunc()
}

Const

-> 변수에 접근하는 코드를 변수에 저장된 값으로 대체시키는 기능

    const는 프로그램 어디서나 사용할 수 있는 변수에 붙이거나, object의 프로퍼티에 붙일 수 있다.

    const가 붙은 변수에는 리터럴로 이루어진 표현식만 저장이 가능하다.

 

❗️코틀린에서는 리터럴만 와야 하는 곳이 몇 군데 있다. 이런 곳에 const가 붙은 변수를 사용하면 바로 리터럴로 대체되기 때문에 사용이         편하다. 

 

const val str = "Hello" + "Kotlin"

object Aa {
    const val bb = "Hello"
}

fun main() {
    println(str)   //println("Hello Kotlin") 이랑 문맥상 같다.
    println(Aa.bb) //println("Hello") 랑 문맥상 같다.
}

 

lateinit

-> 프로퍼티의 초기화를 유예하는 기능의 키워드

 

❗️클래스의 프로퍼티는 선언과 동시에 초기화하거나 init 블록 안에서 초기화를 하는 방법이 있다.

----> 이러한 강제성은 사용상 불편한 점이 많다!!

 

class Point(val x: Int, val y: Int)

class Rectangles {
    lateinit var p1: Point //초기화를 뒤로 미룰 수 있다.
    lateinit var p2: Point

    val width: Int
        get() = p2.x - p1.x
    val height: Int
        get() = p2.y - p1.y

    val size get() = width * height
}

fun main() {
    val rectangle = Rectangles()
    rectangle.p1 = Point(0,0)
    rectangle.p2 = Point(5,5)
    println(rectangle.size)	//25 출력...
}

 


상속관계에 있는 확장 함수

open class AAAA

class BB : AAAA()

fun AAAA.greeting() = println("안녕하세요 AA입니다")
fun BB.greeting() = println("안녕하세요 BB입니다")

// 상속관계에 있는 확장함수의 경우 멤버 함수와는 다르게 참조 변수가 실제로 가리키는 자식타입을 따르지 않고 부모타입을 따른다.
fun main() {
    val obj: AAAA = BB()
    obj.greeting()  //안녕하세요 AA입니다 출력...
}
반응형
Comments