ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 7장 - 연산자 오버로딩과 기타 관례
    Kotlin/코틀린인액션요약 2022. 9. 17. 00:01
    728x90

    7장에서 다루는 내용

    연산자 오버로딩

    관례 : 여러 연산을 지원하기 위해 특별히 이름이 붙은 메서드

    위임 프로퍼티

     

    Point 클래스를 예제로 알아보겠습니다.

    data calss Point(val x: Int, val y: Int)

     

    산술 연산자 오버로딩

    자바에서는 원시 타입에서만 산술 연산자를 사용할 수 있으며 추가로 String에 대해 + 연산자를 사용할 수 있습니다.

    하지만 BigInteger 클래스를 다룬다면 add 메서드를 명시적으로 호출하기보다는 + 연산자를 사용하는 편이 좋습니다.

    또한 컬렉션에 원소를 추가하는 경우에도 += 연산자를 사용할 수 있으면 더 좋습니다.

     

    코틀린에서는 이런 일이 가능합니다.

     

    data class Point(val x: Int, val y: Int){
    	operator fun plus(other: Point): Point{
    		return Point(x + other.x, y + other.y)    
    	}
    }

    plus 함수 앞에 꼭 operator 키워드를 붙여야 합니다.

    이제 + 기호로 두 Point 객체를 더할 수 있습니다.

     

    오버로딩 가능한 이항 산술 연산자들

    a * b = times

    a / b = div

    a % b = mod (1.1부터 rem)

    a + b = plus

    a - b = minus

     

    우선순위는 일반적으로 우리가 아는 연산의 우선순위와 동일하게 동작합니다.

     

    또한 +=와 같은 복합 대입 연산자도 동시에 지원하게 됩니다.

     

    비교 연산자 오버로딩

    코틀린은 ==연산자 호출을 equals 메서드 호출로 컴파일합니다.

    비슷하게 순서 연산자인 <, >, <=, >= 는 compareTo 호출로 컴파일됩니다.

     

    관례를 따르는 get, set 구현하기

    map을 조회하거나 변경할 때 다음과 같이 사용할 수 있습니다.

    val value = map[key]
    mutableMap[key] = newValue

     

    이처럼 Point 클래스 다음과 같은 동작을 구현할 수 있습니다.

    operator fun Point.get(index: Int) : Int{
    	return when(index){
    		0 -> x
    		1 -> y
    		else ->
    			throw IndexOutOfBoundsException("Invalid coordinate index")
    	}
    }

     

    구조 분해 선언과 component 함수

    var (name , ext ) = splitFilename("example.kt")

    구조 분해 선언 구문을 사용하여 데이터 클래스를 name, ext로 나누어서 받을 수 있습니다.

    코틀린 표준 라이브러리에서는 맨 앞의 다섯 원소에 대한 componentN을 제공합니다.

     

    위임 프로퍼티

    필드에 단순히 저장하는 것보다 더 복합한 방식으로 작동하는 프로퍼티를 쉽게 구현할 수 있습니다.

    class Delegate{
    	operator fun getValue(...) {...}
    	operator fun setValue(..., value: Type) {...}
    }
    
    class Foo{
    	var p : Type by Delegate()
    }
    
    var foo = Foo()
    val oldValue = foo.p
    foo.p = newValue

    p 프로퍼티는 접근자 로직을 다른 객체에게 위임합니다.

     

    by 뒤에 있는 식을 계산하여 위임에 쓰일 객체를 얻습니다.

     

    컴파일러는 숨겨진 도우미 프로퍼티를 만들고 그 프로퍼티를 위임 객체의 인스턴스로 초기화합니다.

    class Foo{
    	//컴파일러가 생성한 도우미 프로퍼티
    	private val delegate = Delegate()
    	var p: Type
        
    	//p 프로퍼티를 위해 컴파일러가 생성한 접근자는 delegete의 get,set메서드를 호출합니다.
    	set (value : Type) = delegate.setValue(..., value)
    	get() = delegate.getValue(...)
    }

     

    be lazy()를 사용한 프로퍼티 초기화 지연

    연산이 오래 걸리는 작업이어서 필요한 시점에 객체를 초기화 하고하자 합니다.

    이때 lazy를 활용하면 코드가 간결해지고 스레드에 안전해집니다.

    class Person(val name: String){
    	val emails by lazy{loadEmails(this)}
    }

     

    댓글

Designed by Tistory.