KOTLIN

[KOTLIN] 연산자 오버로드를 할때는 의미에 맞게 사용

집한구석 2022. 7. 3. 10:43
728x90

연산자 오버로딩

  • 어떤 언어 기능과 미리 정해진 이름의 함수를 연결해주는 기법 (자바에서 Iterable 객체에 대해 for Loop를 사용할 수 있는 것 과 비슷함)

산술 연산자 오버로딩

  • 자바는 원시 타입이 String에 대해서만 산술 연산자를 지원하지만 코틀린은 다른 클래스에서 산술연산자를 오버로딩하면 그대로 사용할 수 있음

이항 산술 연산자 오버로딩

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

val p1 = Point(10, 20)
val p2 = Point(30, 40)
println(p1 + p2)
// Point(x=40, y=60)
  • 연산자 오버로딩을 사용시 함수에 operator 키워드를 사용
  • operator 키워드는 어떤 함수가 연산자 오버로딩 Convention을 사용하도록 명시하는 역할을 함

연산자 오버로드를 할 때 의미에 맞게 사용해야하는 이유

//팩토리얼 정의한 확장함수
fun Int.factorial(): Int = (1..this).product()
fun Iterable<Int>.product(): Int = 
		fold(1) { acc, i -> acc * i }

print(10 * 6.facorial()) // 10 * (6!) = 7200

// 연산자 오버로딩
opertaor fun Int.not() = factorial()
print(10 * !6) // 더 간결해..졌나?
  • 함수 이름이 not이라서 논리연산에 맞지 않게 사용했기 때문에 오히려 혼란을 주고 오해의 소지가 발생함
  • 관례에 어긋나는 케이스
  • 하지만 관례에 어긋나도 되는 경우가 있음 

연산자 오버로드에 대하여 관례 및 규칙을 무시해도 되는 경우

// HTML DSL. 코틀린 문법을 활용해서 만든 DSL이다.
body {
	div {
		+"Some Text" // <- String.unaryPlus 가 문자열 앞에 사용되었다.
	}
}

// Gradle DSL. 이것도 코틀린 문법을 이용해서 만든 DSL 이다. Gradle 5.0부터 지원한다.
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.6.10"
    application
}

version = "1.0-SNAPSHOT"

dependencies {
    testImplementation(kotlin("test"))
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

application {
    mainClass.set("MainKt")
}
  • 도메인 특화 언어(Domain Specific Language, DSL)을 설계할 경우 해당 규칙을 무시해도 됨
  • DSL같은 경우 연산자를 잘못 이해할 일이 없기 때문