오늘은 Kotlin 공식 홈페이지 기초 문법에 대한 문제 풀이를 적어보려 합니다. Extension Functions에 대한 내용인데, 공식에서 읽어보라고 한 문서를 읽어도 이해가 잘 안가서리...
문제: Extension functions
Read about extension functions. Then implement extension functions Int.r()
and Pair.r()
and make them convert Int and Pair to RationalNumber
.
fun Int.r(): RationalNumber = TODO()
fun Pair<Int, Int>.r(): RationalNumber = TODO()
data class RationalNumber(val numerator: Int, val denominator: Int)
위 코드가 테스트 케이스에 대해 작동하게 만들기만 하면 됩니다. 두 함수 모두 return 값이 RationalNumber이므로 일단 아래와 같이 러프한 값을 넣어봅니다.
fun Int.r(): RationalNumber = RationalNumber(1, 1)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(1, 1)
data class RationalNumber(val numerator: Int, val denominator: Int)
이러면 아래와 같은 에러가 뜹니다.
Fail: testPairExtension: Rational number creation error: expected:<RationalNumber(numerator=2, denominator=3)> but was:<RationalNumber(numerator=1, denominator=1)>
Fail: testIntExtension: Rational number creation error: expected:<RationalNumber(numerator=4, denominator=1)> but was:<RationalNumber(numerator=1, denominator=1)>
아래와 같이 값을 고치면 해결!!
fun Int.r(): RationalNumber = RationalNumber(4, 1)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(2, 3)
data class RationalNumber(val numerator: Int, val denominator: Int)
Passed: testPairExtension
Passed: testIntExtension
물론 이렇게 값만 러프하게 넣어서 해결해도 되지만;;; 실력 향상을 위해 모든 다른 케이스에 대해서도 동작하도록 만드는 게 중요하겠죠? 상수에서 적절한 변수로 바꿔주면 되겠죠. 그런데 어떤 변수를 넣어야 할지 모르겠습니다. 문제에서 제시한 extension functions 문서를 읽어봅시다. 해당 문서를 첫 문단만 번역해봤습니다.
코틀린에서는 클래스를 상속하거나, 데코레이터 같은 디자인 패턴을 사용하지 않고 클래스를 확장할 수 있습니다. extensions 특별한 선언을 통해 이루어집니다. 이 방법을 통해, 코드를 수정할 수 없는 써드파티 라이브러리 클래스에 새로운 함수를 작성할 수 있습니다. 이런 함수는 원래 메서드와 같은 방법으로 호출할 수 있습니다. 이런 메커니즘은 extension functions라 불립니다. 또한, 이미 정의된 클래스에 새로운 속성을 추가하는 extension properties가 있습니다.
아하! 답이 나왔습니다. 우리가 정의할 Int.r()
과 Pair.r()
은 클래스 메서드로 작동합니다. 그러면 Int와 Pair의 선언을 보면 우리에게 필요한 변수에 대해서도 알 수 있겠죠?
Int에 대한 문서를 보면, 파라미터를 사용하지 않는 메서드는 하나같이 해당 작업을 this
value에 대해 수행한다고 합니다. 우리 코드를 한 번 고쳐볼까요?
fun Int.r(): RationalNumber = RationalNumber(this, 1)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(2, 3)
data class RationalNumber(val numerator: Int, val denominator: Int)
Passed: testPairExtension
Passed: testIntExtension
아까와 마찬가지로 테스트를 패스합니다. 하지만 테스트하려는 값이 바뀌어도 Int.r()
은 계속계속 테스트를 통과하겠죠? 다음으로 Pair에 대한 문서를 찾아봅시다.
Pair는 first와 second, 두 가지 속성을 가지고 있습니다. 그렇다면 메서드에서 사용할 수 있는 값의 이름도 당연히 first와 second겠죠?
fun Int.r(): RationalNumber = RationalNumber(this, 1)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(first, second)
data class RationalNumber(val numerator: Int, val denominator: Int)
Passed: testPairExtension
Passed: testIntExtension
이로써 테스트를 완벽하게 통과했습니다. Extension Functions에 대한 개념은 없어도 눈치코치로 알아맞힐 수 있었는데, 파라미터 값을 몰랐던 건 지금 보니 그냥 기초 지식이 부족했던 것 같네요... 더욱 정진해야겠습니다...
'Android' 카테고리의 다른 글
Kotlin 이슈 4 기능 별로 레이아웃 나누기, include (0) | 2020.02.01 |
---|---|
Object Expressions 코틀린 기초 문법 (3) - Koans 풀이 (0) | 2020.01.28 |
null? 코틀린 기초 문법 (1) - ? ?: !! (0) | 2020.01.24 |
단 5분, 단숨에 AsyncTask 완벽 정복! (0) | 2020.01.23 |
doAsync, AsyncTask, Coroutines 안드로이드 비동기 정답은?! (0) | 2020.01.22 |