Kotlin In Action CH.03 함수 정의와 호출

kez·2023년 7월 25일

Kotlin

목록 보기
1/6

3장에서 다루는 내용

  • 컬렉션, 문자열, 정규식
  • 이름 붙인 인자, 중위 호출 문법
  • 정적인 유틸리티 클래스 없애기: 최상위 함수와 프로퍼티

코틀린에서 Collection 만들기

Collection 이란?

데이터를 저장하는 기본 자료 구조들을 한 곳에 모아 관리와 사용을 편하게 하기 위해 제공하는 프레임 워크크게 List, Set, Map 으로 나뉜다.
collection 안에 있는 object들을 elements 또는 items라고 부른다.

코틀린은 자체 컬렉션 기능을 제공하고 있지 않다.

그 이유로는 표준 자바 컬렉션을 활용하면 자바 코드와 상호작용하기가 훨씬 더 쉽기 때문이다. 즉 자바에서 코틀린 힘수를 호출하거나 코틀린 에서 자바 함수를 호출할 때 자바와 코틀린 컬렉션을 서로 변환할 필요가 없다.

그러나 코틀린에서는 자바보다 더욱 많은 Collection의 기능을 사용할 수 있다. 코틀린 인 액션에서는 다음과 같이 마지막 원소를 가져오거나 수로 이뤄진 컬렉션에서 최댓값을 찾는 예시를 제공한다.

fun main() {
    val strings = listOf("first", "second", "third")
    println(strings.last())
    val numbers = setOf(1,14,2)
    println(numbers.max())
}

answer: 
third
14

이름 붙인 인자

코틀린에서는 이름을 붙인 인자를 활용하여 함수의 가독성을 높일 수 있다.
다음은 joinToString을 활용한 예제이다. 직접 이름을 인자에 붙임으로서 주입되는 변수가 어떠한 역할을 하는지 명시적으로 확인할 수 있도록 도와준다.

fun main() {
    val strings = listOf("first", "second", "third")
    strings.joinToString(",", "", "", -1)
    
    strings.joinToString(
            separator = ",",
            prefix = "",
            postfix = "",
            limit = -1
    )
}

디폴트 파라메터 값

자바에서는 일부 클래스에서 오버로딩(overloading)한 메소드가 너무 많아진다는 문제가 있
다.
코틀린에서는 함수 선언에서 파라메터의 디폴트 값을 지정하여 위와 같은 문제를 해결하였다. 다음 예제를 살펴보자!

public fun <T> Iterable<T>.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String {
    return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString()
}

만약 joinToString의 파라메터에 디폴트 값이 없었더라면 6개의 오버로딩된 함수가 존재했을 것이다. 디폴트 값이 지정된 파라메터는 주입시 생략이 가능하다. 다만 일반 호출 문법을 사용하여 함수를 선언한다면, 같은 순서로 인자를 주입 해야한다.

이름 있는 인자를 사용한다면 인자 목록의 중간을 생략할 수 있으며, 순서와 상관 없이 인자를 주입할 수 있다.

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

코틀린에서는 함수를 직접 소스파일에 위치시켜 최상위 수준 즉 모든 클래스 범위 바깥에서 함수를 선언 할 수 있다. 해당 함수들은 패키지의 멤버 함수이기에 사용시 함수가 정의된 패키지를 import하여 사용해야한다.

위 함수가 실행될 수 있는 이유는 무엇일까? JVM이 클래스 안에 들어있는 코드만을 실행할 수 있기 때문에 컴파일러는 이 파일을 컴파일할 때 새로운 클래스를 정의해주며, 코틀린 컴파일러가 생성하는 클래스의 이름은 최상위 함수가 들어있던 코틀린 소스 파일 의 이름과 대응된다.

public class JoinKt{ 
	public static string joinToString(...) { ... }
}

static으로 함수가 선언되기 때문에 코틀린 파일의 모든 최상위 함수는 이 클래스의 정적인 메소드가 된다.

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

자바와 코틀린 코드를 자연스럽게 통합하는 것이 코틀린의 핵심적인 목표 중 하나라고 설명하고 있다. 하지만 완전히 코틀린 기반 프로젝트는 자바 라이브러리를 기반을 가지고 있기 때문에 변환하지 못하거나 변환하지 않은 코드들을 처리할 수 있어야 한다.

코틀린에서는 확장함수라는 개념을 통해 자바와의 통합을 이루어낸다. 확장함수는 어떤클래스의멤버 메소드인것처럼 호출할 수 있지만 실제로는 그 범위 밖에서 선언된 함수이다. 다음은 마지막 문자열을 반환하는 확장함수 예시이다.

fun String.lastChar() : Char = this[lastIndex]

확장 함수를 만들려면 함수 이름 앞에 확장할 클래스를 선언하면 된다. 클래스의 타입을 수신 객체 타입(receiver type)이라 부르며, 확장 함수가 호출되는 대상이 되는 값 객체를 수신 객체(receiver object)라고 부른다.

profile
Android Developer

1개의 댓글

comment-user-thumbnail
2023년 7월 25일

많은 도움이 되었습니다, 감사합니다.

답글 달기