반응형
연산자 오버로딩 & 기타 관례
- 코틀린이 지원하는 여러 관례(컨벤션)와 관례의 사용법
- 코틀린은 자바클래스를 사용하고 있음. 따라서 자바가 특정 인터페이스를 구현하게 할수는 없음
- 따라서 확장함수를 통해 기존클래스에 새로운 메서드를 추가한다.
- 이를 통해 기존 자바코드를 바꾸지 않고도 새로운 기능을 부여할수 있다.
StringsJVM.kt (kotlin-stdlib)
/**
* Returns `true` if this string is equal to[other], optionally ignoring character case.
*
* Two strings are considered to be equal if they have the same length and the same character at the same index.
* If[ignoreCase] is true, the result of `Char.uppercaseChar().lowercaseChar()` on each character is compared.
*
*@paramignoreCase`true` to ignore character case when comparing strings. By default `false`.
*/
@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
public actual fun String?.equals(other: String?, ignoreCase: Boolean = false): Boolean {
if (this === null)
return other === null
return if (!ignoreCase)
(this as java.lang.String).equals(other)
else
(this as java.lang.String).equalsIgnoreCase(other)
}
특별히 코틀린에서는 연산자에 대응하는 특별한 메소드들을 정의할수 있게 되어있다.
산술연산자 오버로딩
Plus
- 자바에서는 원시타입에 대해 산술연산자를 사용할수 있음
- 특별히 String 에 대해서는 + 를 사용할수 있도록 정의해두었음
- 이외에도 이러한 산술연산자를 정의해서 쓰면 좋은 경우가 있는데,
- 코틀린에서는 이것을 각자 상황에 맞게 정의해서 쓰는것이 가능하다.
이항 산술연산 오버로딩
- operator 키워드를 붙여야한다는 점을 기억한다.
- 관례 Convention : 이러한 방식으로 연산자를 정의하는 것을 의미
operator fun Int.plus(b: Int) = this + b
fun test() {
operator fun Int.plus(b: Any): String {
return "$this $b"
}
println(10 + "ABC")
}
data class Position(val a: Int, val b: Int) {
operator fun plus(item: Position): Position {
return Position(a + item.a, b + item.b)
}
}
class ExampleUnitTest {
@Test
fun test() {
val positionOne = Position(1, 2)
val positionTwo = Position(3, 4)
println(positionOne + positionTwo)
}
}
Function | code |
plus | a + b |
minus | a - b |
div | a / b |
rem | a % b |
times | a * b |
not | !a |
unaryPlus | +a |
unaryMinus | -a |
inc | ++a, a++ |
dec | –a, a– |
class ExampleUnitTest {
@Test
fun test() {
var position = Position(1, 2)
println(position++)
println(++position)
}
}
data class Position(var a: Int, var b: Int) {
operator fun inc(): Position {
return Position(a.inc(), b.inc())
}
}
Android CoroutineScope
private val job = SupervisorJob()
private val uiScope = CoroutineScope(Dispatchers.Main + job)
CoroutineScope.kt
public operator fun CoroutineScope.plus(context: CoroutineContext)
: CoroutineScope =
ContextScope(coroutineContext + context)
CoroutineContext.kt
public operator fun plus(context: CoroutineContext): CoroutineContext =
if (context === EmptyCoroutineContext) this else // fast path -- avoid lambda creation
context.fold(this){acc, element->
val removed = acc.minusKey(element.key)
if (removed === EmptyCoroutineContext) element else {
// make sure interceptor is always last in the context (and thus is fast to get when present)
val interceptor = removed[ContinuationInterceptor]
if (interceptor == null) CombinedContext(removed, element) else {
val left = removed.minusKey(ContinuationInterceptor)
if (left === EmptyCoroutineContext) CombinedContext(element, interceptor) else
CombinedContext(CombinedContext(left, element), interceptor)
}
}
}
Invoke Operator
이름 없이 호출될 수 있음
class Test{
operator fun invoke(str: String){
print(str)
}
}
fun main(){
val test = Test()
test("wow")
}
// UseCase
class GetAccountLocalUseCase @Inject constructor(
private val localRepository: LocalRepository
) : BaseUseCase() {
operator fun invoke(): Flow<TaskResult<AccountLocal>> =
flow{emit(localRepository.getUserInfo())}.toTaskResult()
}
}
// ViewModel
class MyAddressViewModel @Inject constructor(
val getAccountLocalUseCase: GetAccountLocalUseCase
) : BaseViewModel() {
init {
getAccountLocalUseCase()
.onSuccess { account ->
...
}
.onFailure { it.printStackTrace() }
.call(viewModelScope)
반응형
'코틀린 & Java > 코틀린인액션' 카테고리의 다른 글
Kotlin 범위 관례 인덱스로 원소 접근 Get, Set (0) | 2023.05.09 |
---|---|
Kotlin == 비교연산자 오버로딩 (0) | 2023.05.09 |
코틀린 원시타입(Kotlin Primitive Type) (0) | 2023.04.06 |
코틀린 타입 종류 Null가능성 (0) | 2023.03.27 |
[Kotlin] 스코프 펑션(Scoepe Function) (0) | 2023.03.23 |