3.3 메소드를 다른 클래스에 추가: 확장 함수와 확장 프로퍼티
- 확장함수
package strings
// 문자열의 마지막 문자 반환
// 추가하려는 함수이름 앞에 확장하고자 하는 클래스(수신객체타입)의 이름을 붙이면 된다
//fun String.lastChar(): Char = this.get(this.length-1)
fun String.lastChar(): Char = get(length-1) //this 생략 가능
--------------------
// 수신객체 타입 : String
// 수신객체 : "kotlin"
fun main() {
println("kotlin".lastChar())
}
>>>>>>>>>>>>
n
- 확장함수
- 기존 자바 코드와 코틀린 코드를 자연스럽게 통합을 목표로 한다
- 기존 자바 API를 코틀린으로 재작성 하지 않고도 여러 기능을 사용가능?!
- 어떤 클래스의 멤버 메소드처럼 호출할 수 있지만 클래스 밖에 위치한다
- 위 예제처럼 String 클래스에 새로운 메소드를 추가
- JVM 언어면 가능하다
- 확장함수는 클래스안에 정의된 메소드와 달라서 수신객체 클래스의 private,protected 멤버를 사용할 수 없다.(캡슐화 유지)
3.3.1 임포트와 확장 함수
// 확장함수도 패키지를 import 해야한다
// 같은 이름의 함수 충돌 방지
// as 로 클래스,함수이름 재정의 가능
import strings.lastChar as last
fun main() {
println("kotlin".lastChar())
}
3.3.2 자바에서 확장 함수 호출
// java에서 호출
// 패키지 파일명.확장함수
lastChar = strings.lastChar("Java")
3.3.3 확장 함수로 유틸리티 함수 정의
package strings
//Collection<T> 확장 함수 선언
fun <T> Collection<T>.joinToStringExtension(
separator: String = ", ",
prefix: String = "",
postFix: String = ""
): String {
val result = StringBuilder(prefix)
for ((index, element) in this.withIndex()) { // 수신객체 Collection<T> 타입 컬랙션 객체
if (index > 0) result.append(separator)
result.append(element)
}
result.append(postFix)
return result.toString()
}
// 구체적인 타입을 지엉하면 객체에 리스트로는 호출불가
fun Collection<String>.joinToTypeString(
separator: String = ", ",
prefix: String = "",
postFix: String = ""
): String {
val result = StringBuilder(prefix)
for ((index, element) in this.withIndex()) { // 수신객체 Collection<T> 타입 컬랙션 객체
if (index > 0) result.append(separator)
result.append(element)
}
result.append(postFix)
return result.toString()
}
---------------------------------
import strings.joinToStringExtension
import strings.joinToTypeString
fun main() {
val list = arrayListOf(1, 2, 3)
val strList = arrayListOf("a", "b", "c")
println(list.joinToStringExtension(prefix = "[", postFix = "]"))
println(strList.joinToTypeString())
}
>>>>>>>>>>>>>>>>>.
[1, 2, 3]
a, b, c
3.3.4 확장함수는 오버라이드 할 수 없다
open class View {
open fun click() = println("View Clicked")
}
open class Button: View() {
override fun click() = println("Button Clicked")
}
fun View.showOff() = println("i am View")
fun Button.showOff() = println("i am Button")
fun main() {
val view: View = Button() // view 에지정된 값의 실제 타입에따라 호출메소드가 결정된다.
view.click()
// "i am View" showOff 확장함수는 실제 가르키는 Button 객체 에서 재정의 되지 못한다
// View 수신객체의 값을 반환
// 확장함수는 정적이다.
view.showOff()
}
- 이름과 시그니처가 같은 메서드(=확장함수)와 멤버메서드 호출시 멤버메서드가 우선순위를 갖는다
3.3.5 확장 프로퍼티
// 확장 프로퍼티 선언
val String.lastChar: Char
get() = get(length - 1)
var StringBuilder.lastChar: Char
get() = get(length - 1)
set(value:Char) {
this.setCharAt(length - 1, value) // this 생략가능
}
fun main() {
println("kotlin".lastChar)
val sb = StringBuilder("kotlin?")
sb.lastChar = '!' //TODO single quote??
println(sb)
}
- 일반적인 프로퍼티와 같지만 확장함수처럼 수신객체를 같는다.
'발전로그 > 책장로그-개발' 카테고리의 다른 글
kotlin in action 03 (3.5~3.7) (0) | 2022.03.01 |
---|---|
kotlin in action 03 (3.4) (0) | 2022.02.28 |
kotlin in action 03 (3.1 ~ 3.2) (0) | 2022.02.15 |
kotlin in action 02 (5) | 2022.01.24 |
클린 아키텍처 - 소프트웨어 구조와 설계의 원칙 02 3장 (1) | 2022.01.16 |