[Kotlin] 함수(1)

sw·2022년 1월 1일
0

들어가기에 앞서..

  • 코틀린은 자체 collection을 제공하지 않는데 이는 표준 자바 collection을 활용하면 자바 코드와 상호작용하기가 훨씬 쉽기 때문이다.
  • 다시 말해서, 코틀린 collection은 자바 collection과 똑같은 class이다.
    하지만 확장함수를 통해 자바보다 더 많은 기능을 쓸 수 있다.

1. 함수 호출을 쉽게 만들기

  • 자바 collection에는 디폴트 toString구현이 들어있다.
    이 디폴트 구현을 (1; 2; 3)처럼 원소 사이를 세미콜론으로 구분하고 괄호로 구분하려면 어떻게 해야 할까??
    -> 자바와 달리 코틀린에서는 이런 요구 사항을 처리할 수 있는 함수가 표준 라이브러리에 있다.
fun main() {
    val list = listOf(1, 2, 3)
    println(joinToString(list, "; ", "(", ")"))
}


fun <T> joinToString(
    collection: Collection<T>,
    separator: String,
    prefix: String,
    postfix: String
): String {
    val result = StringBuilder(prefix)

    for ((index, element) in collection.withIndex()) {
        if (index > 0) result.append(separator)
        result.append(element)
    }
    result.append(postfix)
    return result.toString()
}

-> 해당 함수를 그대로 써도 좋으나 함수를 호출할 때마다 매번 4개의 인자를 모두 전달해야하는 단점이 있다.


2. 이름 붙인 인자

joinToString(collection," ", " ", ".")
// 인자로 전달한 각 문자열이 어떤 역할을 하는지 알 수 없다.

joinToString(collection, separator = " ", prefix = " ", postfix = ".")
// 인자의 이름을 명시함으로써 가독성이 좋아진다.

->단, 자바로 작성한 코드를 호출할 땐 이름 붙인 인자를 사용할 수 없다.


3. 디폴트 파라미터 값

fun <T> joinToString(
    collection: Collection<T>,
    separator: String = ", ",
    prefix: String = "",
    postfix: String = ""
): String

>>> joinToString(list, ", ", "", "")
>>> joinToString(list)
>>> joinToString(list,"; ")
  • 함수 호출 시 모든 인자를 쓸 수도 있고, 일부를 생략할 수도 있다.
  • 만약 중간에 있는 인자를 생략하고 싶다면 다음과 같이 이름 붙인 인자를 사용하면 된다.
>>> joinToString(list, postfix=";", prefix="# ")
# 1, 2, 3;

디폴트 값과 자바

  • 자바에는 디폴트 파라미터 값이라는 개념이 없어서 자바 쪽에서 좀 더 편하게 코틀린 함수를 호출하려면 @JvmOverloads를 함수에 추가하면 된다.
  • @JvmOverloads를 함수에 추가하면 코틀린 컴파일러가 자동으로 맨 마지막 파라미터로부터 파라미터를 하나씩 생략한 오버로딩한 자바 메소드를 추가해준다.
/* 자바 */
String joinToString(Collection<T> collection, String separator, 
	String prefix, String postfix);
String joinToString(Collection<T> collection, String separator,
	String prefix);
String joinToString(Collection<T> collection, String separator);
String joinToString(Collection<T> collection);

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

  1. 최상위 함수
    - 코틀린에서는 Util 성격의 정적인 메소드만 모아져 있는 의미없는 클래스들을 없앨 수 있다.
    - 함수를 소스 파일의 최상위 수준, 모든 다른 클래스의 밖에 위치시키면 된다.

    joinToString 함수를 top 패키지에 넣고 join.kt파일을 작성하자.
/* join.kt */
package top
        
fun <T> joinToString(...): String {...}
/* main.kt */
package top.bottom

import top.joinToString

fun main(){
    val list = listOf(1,2,3)
    joinToString(list)
}
  • JVM은 클래스 안에 들어있는 코드만을 실행할 수 있기 때문에 컴파일러는 join.kt 파일을 컴파일할 때 새로운 클래스를 정의해준다.
/* 자바 */

package top;

public class JoinKt{
    public static String joinToString(...) {...}
}
// 클래스의 이름은 최상위 함수가 들어있던 코틀린 소스 파일과 대응한다.
/* 자바 */

import top.JoinKt;

...

JoinKt.joinToString(list,", ", "", "");
// joinToString 호출

파일에 대응하는 클래스의 이름 변경하기

  • 코틀린 최상위 함수가 포함되는 클래스의 이름을 바꾸고 싶다면 파일에 @JvmName을 추가하면 된다.
    단, 파일의 맨 앞, 패키지 이름 선언 이전에 위치해야 한다.
@file:JVmName("StringFunctions")	// 클래스 이름 지정
package top
fun joinToString(...): String {...}
/* 자바 */
import top.StringFunctions;
StringFunctions.joinToString(list,", ", "", "");
  1. 최상위 프로퍼티
  • 함수와 마찬가지로 프로퍼티도 파일의 최상위 수준에 놓을 수 있다.
    이를 활용해 코드에 상수를 추가할 수 있다.
val UNIX_LINE_SEPARATOR = "\n"
  • 최상위 프로퍼티도 다른 모든 프로퍼티처럼 접근자 메소드를 통해 자바 코드에 노출된다.( val은 getter, var은 getter, setter가 생긴다. )
    겉으로는 상수처럼 보이는데 실제로 getter를 사용한다면 자연스럽지 못하기 때문에 상수를 public static final필드로 컴파일 해야 한다.

  • const를 추가하면 프로퍼티를 public static final 필드로 컴파일하게 만들 수 있다. ( 단, 원시 타입과 String만 const로 지정 가능)

const val UNIX_LINE_SEPARATOR = "\n"
profile
끄적끄적

0개의 댓글