Kotlin 함수 정의와 호출

INJE YUN·2020년 12월 21일
0

kotlin-in-action

목록 보기
2/2
post-custom-banner

1.

코틀린은 자체 컬렉션 클래스를 정의하지 않지만 자바 클래스를 확장해서 더 풍부한 API를 제공한다.

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

2. 이름 붙인 인자와 디폴트 파라미터 값

함수 파라미터의 디폴트 값을 정의하면 오버로딩한 함수를 정의할 필요성이 줄어든다. 이름붙인 인자를 사용하면 함수의 인자가 많을 때 함수 호출의 가독성을 더 향상시킬 수 있다.

이름을 붙인 인자

fun sum(a: Int, b: Int) {
	a + b
}

fun main() {
  sum(a = 1, b = 2)
}

디폴트 파라미터 값

fun sum(a: Int, b: Int = 1) = a + b
fun minux(a: Int = 2, b: Int) = a - b

fun main() {
  sum(a = 2) // = sum(a = 2, b = 1) = sum(2, 1)
	minus(b = 1) //  = minus(a = 2, b = 1) = minus(2, 1)
	minus(1) // Compile Error. ( No value passed for parameter 'b' )
}

함수의 매개변수에 기본값을 설정 할 수 있다. 일반 호출 문법을 사용하여 함수를 호출할 때는 함수 선언할 때와 같은 순서로 인자를 지정해야 한다. 그런 경우 일부를 생략하면 뒷부분의 인자들이 생략된다. 이름 붙인 인자를 사용하는 경우에는 인자 목록의 중간에 있는 인자를 생략하고, 지정하고 싶은 인자를 이름을 붙여 순서와 관계없이 지정할 수 있다.

3. 최상위 함수와 프로퍼티

코틀린 파일에서 클래스 멤버가 아닌 최상위 함수와 프로퍼티를 직접 선언할 수 있다. 이를 활용하면 코드 구조를 더 유연하게 만들 수 있다.

프로젝트를 진행하다보면, 어느 한 클래스에 포함시키기 어려운 코드가 많이 생긴다. 이렇게 다양한 정적 메소드를 모아두는 역할만 담당하며, 특별한 상태나 인스턴스 메소드가 없는 클래스가 생겨난다. JDK의 Collections 클래스, 우리가 작성하는 ***Util 클래스가 대표적인 예다.

@file:JvmName("TestFunctions") // 클래스 이름을 지정하는 annotation.  이름을 지정하지 않으면, 파일명(맨 앞글자 대문자) + Kt 선언됨. ( e.g. join.kt >> JoinKt )

package util // @file:JvmName annotation 뒤에 패키지 문이 와야 한다.

var a = 0
fun test() {
  println("test")
  a ++
}

util/test.kt의 변수 a와 test 메소드를 Java와 Kotlin 코드에서는 아래와 같이 사용한다.

import static util.TestFunctions.test;

public class Main {
  public void mainMethod() {
    test();
  }
}
import util.test // test.kt의 test 메소드 

class Main2 {
  fun mainMethod() {
    test()
  }
}

4. 확장 함수와 확장 프로퍼티

확장 함수와 프로퍼티를 사용하면 외부 라이브러리에 정의된 클래스를 포함해 모든 클래스의 API를 그 클래스의 소스코드를 바꿀 필요 없이 확장할 수 있다. 확장 함수를 사용해도 실행 시점에 부가비용이 들지 않는다.

확장 함수와 프로퍼티를 사용하면 외부 라이브러리에 정의된 클래스를 포함해 모든 클래스의 API를 그 클래스의 소스코드를 바꿀 필요 없이 확장할 수 있다. 확장 함수를 사용해도 실행 시점에 부가비용이 들지 않는다.

확장 함수와 확장 프로퍼티는 어떤 클래스의 멤버 메소드와 변수인 것처럼 호출할 수 있지만 그 클래스의 밖에서 선언된 함수와 변수이다. 확장 함수를 만들려면 추가하려는 함수 이름 앞에 그 함수가 확장할 클래스의 이름을 덧붙이면 된다. 클래스 이름을 수신 객체 타입(receiver type)이라 부르며, 확장 함수가 호출되는 대상이 되는 값(객체)을 수신 객체(receiver object)라 부른다.

// stringUtil.kt
fun String.lastChar(): Char = this.get(this.length - 1)

// intUtil.kt
fun Int.plusAndMinus(a: Int, b: Int) = this + a - b

"abc".lastChar() // 'c' 반환
1.plusAndMinus(2, 3) // 0 반환

내부적으로 확장 함수는 수신 객체를 첫 번째 인자로 받는 정적 메소드라서, Java에서 해당 함수를 호출하려면 첫 번째 인자로 수신 객체를 넘겨야한다.

StringUtilKt.lastChar("abc") // 'c' 반환
IntUtilKt.plusAndMinus(1, 2, 3) // 0 반환

5.

중위 호출을 통해 인자가 하나 밖에 없는 메소드나 확장 함수를 더 깔끔한 구문으로 호출할 수 있다.

infix fun Any.to(other: Any) = Pair(this, other)

1.to("one")
2 to "two"

6.

코틀린은 정규식과 일반 문자열을 처리할 때 유용한 다양한 문자열 처리 함수를 제공한다.

7.

자바 문자열로 표현하려면 수많은 이스케이프가 필요한 문자열의 경우 3중 따옴표 문자열을 사용하면 더 깔끔하게 표현할 수 있다.

8.

로컬 함수를 써서 코드를 더 깔끔하게 유지하면서 중복을 제거할 수 있다.

profile
신입 개발자입니다.
post-custom-banner

0개의 댓글