Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- mybatis
- 스프링 부트
- Spring Boot
- Collections
- Spring Mail
- maven
- 스프링 스케줄러
- spring scheduler
- 스프링 메일
- 의존성관리
- pair
- java
- Arrays
- C++
- Dependency
- @Scheduled
- vuejs #vue #js #프론트엔드 #nodejs #클라이언트사이드 #템플릿엔진
- list
- springboot
- 프로그래머스
- pom.xml
- 프로젝트 구조
- 코딩테스트
- GOF
- thymeleaf
- HashMap
- 스프링
- Spring
- codility
- 스프링부트
Archives
- Today
- Total
Rooted In Develop
Kotlin - 연산자 오버로딩 본문
산술 연산자 오버로딩
이항 산술 연산 오버로딩
연산자 | 키워드 |
a * b | times |
a / b | div |
a % b | mod |
a + b | plus |
a - b | minus |
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 fun Point.times(scale: Double) : Point {
return Point((x * scale).toInt(), (y * scale).toInt())
}
>>> val p = Point(10, 20)
>>> println(p * 1.5)
Point(x=15, y=30)
- 자동으로 교환 법칙을 지원하지 않음
- 1.5 * p 를 오버로딩하려면 operator fun Double.times(p: Point) : Point 를 정의해야함
결과 타입이 다른 경우
operator fun Char.times(count: Int) : String {
return toString().repeat(count)
}
>>> println('a' * 3)
aaa
복합 대입 연산자 오버로딩
연산자 | 키워드 |
+= | plusAssign |
-= | minusAssign |
*= | timesAssign |
- ex) a += b 는 a = a.plus(b) 또는 a.plusAssign(b)
컬렉션
- +=, -= : 새로운 컬렉션 반환
- +, - : 객체 상태 변화
단항 연산자 오버로딩
연산자 | 키워드 |
+a | unaryPlus |
-a | unaryMinus |
!a | not |
++a, a++ | inc |
--a, a-- | dec |
operator fun Point.unaryMinus() : Point {
return Point(-x, -y)
}
>>> val p = Point(10, 20)
>>> println(-p)
Point(x=-10, y=-20)
비교 연산자 오버로딩
동등성 연산자 : 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)
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
컬렉션과 범위에 대해 쓸 수 있는 관례
인덱스로 원소에 접근 : get, set
operator fun Point.get(index: Int) : Int {
return when(index) {
0 -> x
1 -> y
else -> throw IndexOutOfBoundsException("Invalid coordinate $index")
}
}
>>> val p = Point(10, 20)
>>> println(p[1])
20
data class MutablePoint(var x: Int, var y: Int)
operator fun MutablePoint.set(index: Int, value: Int) {
when(index) {
0 -> x = value
1 -> y = value
else -> throw IndexOutOfBoundsException("Invalid coordinate $index")
}
}
>>> val p = MutablePoint(10, 20)
>>> p[1] = 42
>>> println(p)
MutablePoint(x=10, y=42)
in 관례
data class Rectangle(val upperLeft: Point, val lowerRight: Point)
operator fun Rectangle.contains(p: Point) : Boolean {
return p.x in upperLeft.x until lowerRight.x && p.y in upperLeft.y until lowerRight.y
}
>>> val rect = Rectangle(Point(10, 20), Point(50, 50))
>>> println(Point(20, 30) in rect)
true
>>> println(Point(5, 5) in rect)
false
rangeTo 관례
>>> val now = LocalDate.now()
>>> val vacation = now..now.plusDays(10)
>>> println(now.plusWeeks(1) in vacation)
true
for 루프를 위한 iterator 관례
operator fun ClosedRange<LocalDate>.iterator() : Iterator<LocalDate> = object : Iterator<LocalDate> {
val current = start
override fun hasNext() = current <= endInclusive
override fun next() = current.apply {
current = plusDays(1)
}
}
>>> val newYear = LocalDate.ofYearDay(2017, 1)
>>> val daysOff = newYear.minusDays(1)..newYear
>>> for (dayOff in daysOff) { println(dayOff) }
2016-12-31
2017-01-01
구조 분해 선언과 component 함수
>>> val p = Point(10, 20)
>>> val (x, y) = p
>>> println(x)
10
>>> println(y)
20
val (a, b) = p
- val a = p.component1()
- val b = p.component2()
- componentN 함수 호출로 변환됨
data class NameComponents(val name: String, val extension: String)
fun splitFilename(fullName: String) : NameComponents {
val result = fullName.split('.', limit = 2)
return NameComponents(result[0], result[1])
}
>>> val (name, ext) = splitFilename("example.txt")
>>> println(name)
example
>>> println(ext)
txt
data class NameComponents(val name: String, val extension: String)
fun splitFilename(fullName: String) : NameComponents {
val (name, extension) = fullName.split('.', limit = 2)
return NameComponents(name, extension)
}
fun printEntries(map: Map<String, String>) {
for ((key, value) in map) {
println("$key -> $value")
}
}
>>> val map = mapOf("Oracle" to "Java", "JetBrains" to "Kotlin")
>>> printEntries(map)
Oracle -> Java
JetBrains -> Kotlin
프로퍼티 접근자 로직 재활용 : 위임 프로퍼티
위임 프로퍼티
class Delegate {
operator fun getValue() {}
operator fun setValue() {}
}
class Foo {
var p: Type by Delegate()
}
>>> val foo = Foo()
>>> val oldValue = foo.p
>>> foo.p = newValue
프로퍼티 초기화 지연 : by lazy()
class Email {}
fun loadEmails(person: Person) : List<Email> {
println("${person.name}")
return listOf(/*...*/)
}
class Person(val name: String) {
private var _emails: List<Email>? = null
val emails: List<Email>
get() {
if (_emails == null) {
_emails = loadEmails(this)
}
return _emails!! // 저장해 둔 데이터가 있으면 그 데이터를 반환
}
}
class Person(val name: String) {
val emails by lazy ( loadEmails(this) )
}
위임 프로퍼티 구현
open class PropertyChangeAware {
protected val changeSupport = PropertyChangeSupport(this)
fun addPropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.addPropertyChangeListener(listener)
}
fun removePropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.removePropertyChangeListener(listener)
}
}
// 프로퍼티 변경 통지 직접 구현
class Person(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
var age: Int = age
set(newValue) {
val oldValue = field
field = newValue
changeSupport.firePropertyChange("age", oldValue, newValue)
}
var salary: Int = salary
set(newValue) {
val oldValue = field
field = newValue
changeSupport.firePropertyChange("salary", oldValue, newValue)
}
}
// 도우미 클래스로 프로퍼티 변경 통지 구현
class ObsservableProperty(val propName: String, var propValue: Int, val changeSupport: PropertyChangeSupport ) {
fun getValue() : Int = propValue
fun setValue(newValue: Int) {
val oldValue = propValue
propValue = newValue
changeSupport.firePropertyChange(propName, oldValue, newValue)
}
}
class Person(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
val _age = ObservableProperty("age", age, changeSupport)
var age: Int
get() = _age.getValue()
set(value) { _age.setValue(value) }
val _salary = ObservableProperty("salary", salary, changeSupport)
var salary: Int
get() = _salary.getValue()
set(value) { _salary.setValue(value) }
}
// ObservableProperty를 프로퍼티 위임에 사용할 수 있도록 변경
class ObservableProperty(var propValue: Int, val changeSupport: PropertyChangeSupport) {
operator fun getValue(p: Person, prop: KProperty<*>): Int = propValue
operator fun setValue(p: Person, prop: KProperty<*>, newValue: Int) {
val oldValue = propValue
propValue = newValue
changeSupport.firePropertyChange(prop.name, oldValue, newValue)
}
}
// 위임 프로퍼티를 통해 프로퍼티 변경 통지 받기
class Person(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
var age: Int by ObservableProperty(age, changeSupport)
var salary: Int by ObservableProperty(salary, changeSupport)
}
// Delegates.observable 사용해서 프로퍼티 변경 통지 구현
class Person(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
private val observer = {
prop: KProperty<*>, oldValue: Int, newValue: Int -> changeSupport.firePropertyChange(prop.name, oldValue, newValue)
var age: Int by Delegates.observable(age, observer)
var salary: Int by Delegates.observable(salary, observer)
}
}
위임 프로퍼티 컴파일 규칙
val x = c.prop / val x = <delegate>.getValue(c, <property>)
c.prop = x / <delegate>.setValue(c, <property>, x)
프로퍼티 값을 맵에 저장
class Person {
// 추가 정보
private val _attributes = hashMapOf<String, String>()
fun setAttribute(attrName: String, value: String) {
_attributes[attrName] = value
}
// 필수 정보
val name: String
get() = _attributes["name"]!!
}
위임 프로퍼티로 맵에 저장
class Person {
private val _attributes = hashMapOf<String, String>()
fun setAttribute(attrName: String, value: String) {
_attributes[attrName] = value
}
val name: String by _attributes
}
프레임워크에서 위임 프로퍼티 활용
object Users : IdTable() {
val name = varchar("name", length = 50).index()
val age = integer("age")
}
class User(id: EntityID) : Entity(id) {
var name: String by Users.name
var age: Int by Users.age
}
'Back End > Kotlin' 카테고리의 다른 글
Kotlin - 제네릭스 (0) | 2023.06.10 |
---|---|
Kotlin - 고차 함수 (0) | 2023.06.03 |
Kotlin - 타입 시스템 (0) | 2023.05.06 |
Kotlin - 클래스, 객체, 인터페이스 (0) | 2023.05.01 |
Kotlin - 람다 프로그래밍 (0) | 2023.05.01 |
Comments