[코틀린 인 액션] CH7 연산자 오버로딩과 기타 관례✍

0

코틀린 인 액션

목록 보기
8/13
post-thumbnail

[코틀린 인 액션] CH7 연산자 오버로딩과 기타 관례

이 포스팅은 <<Kotlin in Action>>, 드미트리 제메로프 & 스베트라나 이사코바, 에이콘출판사(2017)을 읽고 개인 학습용으로 정리한 글입니다.

  • 관례(convention): 언어 기능과 미리 정해진 이름의 함수를 연결해주는 기법

  • 기존 자바 클래스에 대해 확장 함수 구현하면서 관례에 따라 이름 붙이면
    기존 자바 코드를 바꾸지 않아도 새로운 기능 쉽게 부여 가능

7.1 산술 연산자 오버로딩

7.1.1 이항 산술 연산자 오버로딩

  • operator 키워드: 어떤 함수가 관례를 따르는 함수임을 명시
    -> 연산자를 오버로딩하는 함수 앞에는 꼭 operator 있어야

  • operator 함수도 오버로딩 가능
    -> 이름은 같지만 파라미터 타입 서로 다른 연산자 함수 여러개 가능

  • operator가 없는데 실수로 관례에서 사용하는 함수 이름을 쓰고 우연히 그 이름에 해당하는 기능을 사용하는 경우 operator modifier is required... 오류 발생

  • 연산자를 멤버 함수로 만드는 대신 확장 함수로 정의할 수도 있다
    -> 외부 클래스에 대한 연산자를 정의할 때는 관례를 따르는 이름의 확장 함수로 구현하는 게 일반적인 패턴

  • 코틀린에서는 프로그래머가 직접 연산자를 만들어 사용 X
    언어에서 미리 정해둔 연산자만 오버로딩 가능
    -> 관례에 따르기 위해 클래스에 정의해야 하는 이름 연산자별로 정해져 있음

  • 오버로딩 가능한 이항 산술 연산자: times, div, mod(rem), plus, minus

  • 연산자 우선순위 언제나 표준 숫자 타입에 대한 연산자 우선순위와 같음

  • 연산자 정의할 때 두 피연산자 같은 타입일 필요 X

    • 코틀린 연산자가 자동으로 교환 법칙 지원 X
  • 연산자 함수의 반환 타입 꼭 두 피연산자 중 하나와 일치할 필요 X

7.1.2 복합 대입 연산자

  • 복합 대입 연산자(compound assignment)

  • plus와 같은 연산자를 오버로딩하면
    -> 코틀린은 + 연산자 뿐 아니라 그와 연관된 += 연산자도 자동으로 함께 지원
    -> 변수가 변경 가능한 경우에만 += 사용 가능

  • 경우에 따라 += 연산이 객체에 대한 참조를 바꾸기 보다 원래 객체의 내부 상태를 변경하게 만들고 싶을 때
    -> 반환 타입 Unit인 plusAssign 함수 정의

  • 이론적으로 +=를 plus와 plusAssign 양쪽으로 컴파일 가능
    -> 어떤 클래스가 이 두 함수 모두 정의 & 둘다 사용 가능한 경우 컴파일러는 오류 보고
    -> plus와 plusAssign 동시에 정의 X

  • 코틀린 표준 라이브러리는 컬렉션에 대해 두 가지 접근 방법 함께 제공

    • +, -: 항상 새로운 컬렉션 반환
    • +=, -=: 변경 가능한 컬렉션에서는 항상 메모리에 있는 객체 상태 변화
    • +=, -=: (var로 선언한) 읽기 전용 컬렉션에서는 항상 변경을 적용한 복사본 반환

7.1.3 단항 연산자 오버로딩

  • 오버로딩 가능한 단항 산술 연산자: unaryPlus, unaryMinus, not, inc, dec

  • inc, dec 함수를 정의해 증가/감소 연산자를 오버로딩하는 경우
    -> 컴파일러는 일반적인 값에 대한 전위, 후위 증가/감소 연산자와 같은 의미 제공

7.2 비교 연산자 오버로딩

7.2.1 동등성 연산자: equals

  • 코틀린 == 연산자: equals 메서드 호출로 컴파일

  • a==b
    -> a?.equals(b) ?: (b==null)

  • == 와 != 내부에서 인자가 널인지 검사
    -> 다른 연산과 달리 널이 될 수 있는 값에도 적용 가능

class Point(val x: Int, val y: Int){
    override fun equals(obj:Any?):Boolean{
        if(obj === this) return true 
        if (obj !is Point) return false
        return obj.x == x && obj.y == y
    }
}

fun main() {
    println(Point(10, 20) == Point(10, 20))
    println(Point(10, 20) == Point(1, 2))
    println(Point(10, 20) == null)
}
  • 식별자 비교 연산자(===): 자신의 두 피연산자가 서로 같은 객체를 가리키는지 비교
    -> 자바의 == 연산자와 같음
    -> === 연산자를 오버로딩할 수 X

  • Any에 정의된 메서드이므로 다른 연산자 오버로딩 관례와 달리 override 사용
    -> Any의 equals에 operator가 붙어있음

  • Any에서 상속받은 equals가 확장 함수보다 우선순위 높음
    -> equals 확장 함수로 정의할 수 X

7.2.2 순서 연산자: compareTo

  • 자바에서 정렬이나 최댓값, 최솟값 등을 비교해야하는 알고리즘: Comparable 인터페이스 구현해야
    -> Comparable에 들어있는 compareTo 메서드: 한 객체와 다른 객체의 크기 비교해 정수로 나타냄

  • 코틀린은 Comparable 인터페이스 안에 있는 compareTo 메서드를 호출하는 관례 제공
    -> 비교 연산자는 compareTo로 컴파일됨

  • a>=b
    -> **a.compareTo(b) >= 0

  • compareValuesBy: 두 객체의 대소를 알려주는 0이 아닌 값이 나올 때까지 인자로 받은 함수를 차례로 호출해 두 값 비교
    -> 모든 함수 0 반환하면 0 반환
    -> ⚡각 비교 함수는 람다나 프로퍼티/메서드 참조일 수 있다

  • Comparable 인터페이스를 구현하는 모든 자바 클래스
    -> 코틀린에서는 연산자 구문으로 비교 가능
    -> 확장 메서드 만들 필요 X

7.3 컬렉션과 범위에 대해 쓸 수 있는 관례

7.3.1 인덱스로 원소에 접근: get과 set

  • 코틀린에서는 인덱스 연산자도 관례를 따름
    • get: 인덱스 연산자를 사용해 원소 읽는 연산
    • set: 인덱스 연산자를 사용해 원소 쓰는 연산
class Point(val x: Int, val y: Int)

fun main() {
     operator fun Point.get(index:Int):Int{
        return when(index){
            0 -> x
            1 -> y
            else -> throw IndexOutOfBoundsException("Invalid coordinate ${index}")
        }
    }
     
    val point = Point(10, 20)
    println("${point[0]} ${point[1]}")
}
  • get 메서드의 파라미터로 Int가 아닌 타입 사용 가능
    -> ex. 맵의 get 파라미터 타입: 맵의 키 타입

7.3.2 in 관례

  • in: 객체가 컬렉션에 들어있는지 검사 = 멤버십 검사
    -> contains 함수와 대응

7.3.3 rangeTo 관례

  • .. 연산자는 rangeTo 함수를 간략하게 표현하는 방법
    -> rangeTo 함수는 범위 반환

  • start .. end
    -> start.rangeTo(end)

  • 코틀린 표준 라이브러리에는 모든 Comparable 객체에 대해 적용 가능한 rangeTo 함수 존재
    -> 어떤 클래스가 Comparable 인터페이스를 구현하면 rangeTo 구현할 필요 X

  • 어떤 원소가 그 범위 안에 들어있는지 in을 통해 검사 가능

  • 범위 연산자는 우선순위 낮음
    -> 범위의 메서드를 호출하려면 범위 괄호로 둘러싸야

7.3.4 for 루프를 위한 iterator 관례

✍...

profile
Be able to be vulnerable, in search of truth

0개의 댓글