본문 바로가기
kotlin

[Kotlin in Action] 3장: 함수의 정의와 호출

by 권성호 2023. 2. 8.

3.1  코틀린에서 컬렉션 만들기

  • 컬렉션을 만드는 유용한 메서드를 제공
  • 코틀린의 컬렉션은 내부적으로 자바의 컬렉션을 그대로 사용하면서 이를 확장
    • 기존 자바 코드와의 호완성을 위함
    • 확장을 통해 기존 자바 클래스보다 더 많은 기능을 제공

3.2 함수를 호출하기 쉽게 만들기

기본 셈플 함수 형태

fun <T> joinToString(
        collection: Collection<T>,
        separator: String,
        prefix: String,
        postfix: String
        ) : String {
    val sb = StringBuilder(prefix)
    for ((idx, ele) in collection.withIndex()) {
    sb.append(ele)
    if(collection.size -1 > idx) sb.append(separator)
    }
    sb.append(postfix)
    return sb.toString()
}
  • 호출 코드
fun main(args: Array<String>) {
    val mySet = hashSetOf(1,2,3)
    println(joinToString(mySet, "~","[","]"))
}
  • 불편사항
    • 메소드메서드 호출부를 보면 어떤 인자가 어떤 역할을 하는지 명시적으로 알기 어려움

3.2.1 이름 붙인 인자 <- 함수를 사용하는 쪽의 편의

  • 메서드 호출부에 이름을 명시적으로 지정할 수 있음
fun main(args: Array<String>) {
    val mySet = hashSetOf(1,2,3)
    println(joinToString(mySet, separator = "~",prefix = "[",postfix = "]"))
}
  • 이름을 지정하면 메소드 호출 시 파라미터 순서 안 지켜도 상관없음

3.2.2 디폴트 파라미터 <- 함수를 선언하는 쪽의 편의

fun <T> joinToString(
        collection: Collection<T>,
        separator: String = ",",
        prefix: String = "[",
        postfix: String = "]"
        ) : String {
    val sb = StringBuilder(prefix)
    for ((idx, ele) in collection.withIndex()) {
    sb.append(ele)
    if(collection.size -1 > idx) sb.append(separator)
    }
    sb.append(postfix)
    return sb.toString()
}
  • 호출하는 쪽에서 여러 형태로 호출 가능
    • 메소드오버로딩의 부분을 줄여줌
    • (메서드 오버로딩도 일종의 중복이라고 볼 수 있음)

3.2.3 정적인 유틸리티 클래스 없애기: 최상위 함수와 프로퍼티

  • 코틀린의 메서드와 프로퍼티는 반드시 클래스 내부에 선언할 필요가 없음
  • 클래스 밖에 선언된 메서드와 프로퍼티를 최상위 메서드, 프로퍼티라 함
  • 최상위 메서드, 프로퍼티는 자바의 static과 유사한 성질을 가짐(내부적으로 동일)

3.3 메서드를 다른 클래스에 추가: 확장 함수와 프로퍼티

  • 개념
    • 어떤 클래스의 멤버 메서드인 것처럼 호출
    • 하지만, 실제로 멤버 메서드는 아니고 외부에 정의된 정적 메소드
    • 프락시처럼 클라이언트는 멤버 메서드를 호출한다고 생각하지만 내부적으로는 그 멤버 메소드를 확장한 메소드를 호출하게 됨
    • 이러한 형태로 기존 멤버 메서드에 부가기능 추가 & 접근제어를 가능하게 함
  • 문법
fun String.lastChar() : Char = this.get(this.length - 1)
  • 자바에서의 노출
    • 코틀린의 확장함수는 자바로 치면 수신 객체 타입의 인스턴스를 가장 처음 인자로 받는 정적 메서드로 표현됨
  • 예시: joinToString 메소드를 Collection 의 확장함수 형태로 구현
fun <T> Collection<T>.joinToString(
        separator: String,
        prefix: String,
        postfix: String
) : String{
    val sb = StringBuilder(prefix)
    for ((idx, ele) in this.withIndex()) {
        sb.append(ele)
        if(this.size -1 > idx) sb.append(separator)
    }
    sb.append(postfix)
    return sb.toString()
}
  • 호출하는 부분
fun main(args: Array<String>) {
    val mySet = hashSetOf(1,2,3)
    println(mySet.joinToString(separator = "~",prefix = "[",postfix = "]"))
}
  • 확장함수는 내부적으로 자바의 static 메소드로 동작
    • 오버라이딩이 불가능
    • 동적바인딩이 아니라 정적바인딩됨
  • 멤버 메서드와의 우선순위
    • 동일한 형태의 클라이언트 호출 코드가 있으면 멤버메서드가 확장함수보다 우선순위 높음
  • 확장 프로퍼티
    • 확장 함수와 마찬가지로
      • 클래스 외부에서 정의
      • 수신객체클래스가 추가된 형태
    • 클래스 외부에 정의되기 때문에 상태를 저장할 방법이 없음
      • 즉, 뒷받침하는 필드가 없음

이후 문자열 부분은 생략

댓글