개발/Kotlin

연산자 오버로딩과 기타 관례(convention) (1/3)

귀찮은게 많은 개발자 2022. 1. 5. 14:35
728x90
  • 이항 산술 연산 오버로딩
    • 오버로딩 가능한 이항 산술 연산자
함수 이름
a * b times
a / b div
a % b mod (1.1 부터 rem)
a + b plus
a - b minus

 

// plus 연산자 구현하기
data class Point(val x: Int, val y: Int) {
	// 연산자를 오버로딩 하는 함수 앞에는 operator 가 꼭 있어야한다.
	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)  // operator 키워드로 plus를 선언해서 + 기호로 두 객체를 더할 수 있다.
Point(x=40, y=60)


// 연산자를 확장 함수로 정의하기
operator fun Point.plus(other: Point): Point {
	return Point(x + other.x, y + other.y)
}

 

  • 비트 연산자
    • 비트 연산자는 특별한 연산자 함수를 사용하지 않는다.
    • 코틀린은 표준 숫자 타입에 대해 비트 연산자를 정의하지 않았다.
  코틀린 연산자 자바 연산자
shl 왼쪽 시프트 <<
shr 오른쪽 시프트 >>
ushr 오른쪽 시프트 >>>
and 비트 곱 &
or 비트 합 |
xor 비트 배타 합 ^
inv 비트 반전 ~

 

  • 복합 대입 연산자 오버로딩
    • +=, -= 등의 연산자를 복합 대입(compound assignment) 연산자라고 한다.
    • +, - 는 항상 새로운 컬렉션을 반환한다.
    • +=, -= 는 항상 변경 가능한 컬렉션에 작용해 메모리에 있는 객체 상태를 변화시킨다.
    • 읽기 전용 컬렉션에서 +=, -= 는 변경을 적용한 복사본을 반환한다.
>>> var point = Point(1, 2)
>>> point += Point(3, 4)
>>> println(point)
Point(x=4, y=6)

// += 연산이 원래 객체의 내부 상태를 변경하게 하는 예제
>>> val numbers = ArrayList<Int>()
>>> numbers += 42
>>> println(numbers[0])
42

// plusAssign
operator fun <T> MutableCollection<T>.plusAssign(element: T) {
	this.add(element)
}

 

  • 단항 연산자 오버로딩
    • 미리 정해진 이름의 함수를 선언하면서 operator로 표시하면 된다.
함수 이름
+a unaryPlus
-a unaryMinus
!a not
++a,, a++ inc
--a, a-- dec
operator fun Point.unarryMinus(): Point {
	return Point(-x, -y)
}

>>> val p = Point(10, 20)
>>> println(-p)
Point(x=-10, y=-20)


// 증가 연산자 정의하기
operator fun BigDecimal.inc() = this + BigDecimal.ONE

>>> var bd = BigDecimal.ZERO
>>> println(bd++)
0
>>> println(++bd)
2

 

  • equals
    • == 연산자 호출을 equals 메소드 호출로 컴파일한다.
    • != 연산자를 사용해도 equals 호출로 컴파일된다.
    • a == b 코틀린은 a 가 null 인지 판단해서 null 이 아닌 경우에만 a.equals(b)를 호출한다.
    • 식별자 비교 (identity equals) === 는 오버 로딩할 수 없다.
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
	}
}

>>> println(Point(10, 20) == Point(10, 20))
true
>>> println(Point(10, 20) != Point(5, 5))
true
>>> println(null == Point(1, 2))
false

 

  • compareTo
    • a >= b --> a.compareTo(b) >= 0 으로 컴파일된다.
class Person (val firstName: String, val lastName: String) : Comparable<Person> {
	override fun compareTo(other: Person): Int {
		return compareValuesBy(this, other, Person::lastName, person::firstName)
	}
}

>>> val p1 = Person("Alice", "Smith")
>>> val p2 = Person("Bob", "Johnson")
>>> println(p1 < p2)
false

>>> println("abc" < "bac")
true

 


나머지 내용은 아래의 링크로 확인해주세요.

https://eddie-rody.tistory.com/17

 

연산자 오버로딩과 기타 관례(convention) (2/3)

https://eddie-rody.tistory.com/16 연산자 오버로딩과 기타 관례(convention) (1/3) 이항 산술 연산 오버로딩 오버로딩 가능한 이항 산술 연산자 식 함수 이름 a * b times a / b div a % b mod (1.1 부터 rem) a..

eddie-rody.tistory.com

 

https://eddie-rody.tistory.com/18

 

연산자 오버로딩과 기타 관례(convention) (3/3)

https://eddie-rody.tistory.com/16 연산자 오버로딩과 기타 관례(convention) (1/3) 이항 산술 연산 오버로딩 오버로딩 가능한 이항 산술 연산자 식 함수 이름 a * b times a / b div a % b mod (1.1 부터 rem) a..

eddie-rody.tistory.com

 

728x90