언어(Programming Language)/Kotlin

[Kotlin] 함수(Function) 사용법

RyanSin 2021. 2. 17. 13:16
반응형

- 지난 시간

안녕하세요. 지난 시간에는 Kotlin의 클래스와 생성자에 대해 알아봤습니다.

 

혹시 놓치고 오신 분들은 아래 링크를 통해 학습하고 오시는 걸 추천드리겠습니다.

any-ting.tistory.com/59

 

[Kotlin] 클래스(Class) 생성자(Constructors) 개념 및 사용법

- 개요 안녕하세요. 이번 시간에는 객체지향 프로그램에서 제일 어려운 개념인... Class(클래스)에 대해 알아보겠습니다. 일단 Class란 무엇일까요?? 딱 머릿속에 생각나는 게 없네요... 등급인가?...

any-ting.tistory.com

 

- 개요

이번 시간에는 코틀린에서 사용되는 함수에 대해 알아보겠습니다.

 

- 함수에 기본 구조

fun getName(): Unit{

    println("개발이 취미인 사람")
    
}

 

코틀린에서는 fun이라는 키워드로 함수를 정의합니다. 그리고 함수명, () 파라미터 값을 설정하며, : 뒤에는 반환 타입을 설정합니다.

 

Unit은 자바에서 사용되는 void와 동일합니다.

 

코틀린에서는 타입 추론이 가능하기 때문에 아래와 같이 반환 타입을 안 적어도 컴파일 시 알아서 타입을 정의합니다.

 

fun getName(){

    println("개발이 취미인 사람")
    
}

 

 

 

기본 사용법

위에 설명을 보면 파라미터는 () 소괄호 안에 정의할 수 있다고 말했습니다.

//name이라는 파라미터가 있는 함수
fun getName(name:String){

    println(name)
    
}

//호출
fun main() {
    getName("개발이 취미인 사람")

    /**
     * 실행 결과
     * 
     * 개발이 취미인 사람
     */
}

 

name이라는 파라미터를 하나 정의했습니다. 한 개가 아닌 여러 개를 선언하고 싶다면, 이름이 다른 변수명으로 쉼표(,) 뒤에 새로운 파라미터를 선언할 수 있습니다.

vararg 파라미터

vararg 파라미터는 우리가 전달받는 값이 만약 정해져 있지 않은 상황에서 사용하기 좋은 한정자입니다.

 

 한정자란 : 속성(변수)이나 기능(함수) 앞에 어떻게 코드를 노출하는지 지정할 때 말은 한다.

 우리는 보통 public 이런 식으로 앞에 접근 제어자처럼 앞에 붙여주는 부분이다. 

 

//값을 합산하는 함수 선언
fun sum(vararg numbers:Int) : Int{

    numbers.forEach { number ->
        //전달 받은 값 확인
        println(number)
    }

    //sum(): IntArray 자료형 함수
    var sum = numbers.sum()

    //결과 반환
    return sum
}

//호출
fun main() {

    var sum = sum(1, 2, 3, 4)

    println(sum)

    /**
      * 실행 결과
      *
      * 1
      * 2
      * 3
      * 4
      * 10
      */
}

 

vararg를 사용하면 여러 값을 전달할 수 있으며, 전달받은 데이터 타입은 배열입니다.

 

사용할 때 주의사항이 있습니다. vararg는 파라미터에서 가장 뒤에 선언해서 사용해야 됩니다.

 

//String 타입과 vararg 한정자를 사용한 함수
fun sum(name:String, vararg numbers:Int) : String{

    numbers.forEach { number ->
        //전달 받은 값 확인
        println(number)
    }

    //sum(): IntArray 자료형 함수
    var sum = numbers.sum()

    //결과 반환
    return name+sum
}

//호출
fun main() {

    var sum = sum("총 점수는 : ",1, 2, 3, 4)

    println(sum)
    /**
      * 실행 결과
      *
      * 1
      * 2
      * 3
      * 4
      * 총 점수는 : 10
      */
}

 

위와 같이 사용하지 않고 만약 파라미터 순서를 변경한다면 호출할 때 에러를 발생합니다. name과 numbers 순서를 변경하고 호출해보겠습니다.

 

Error...

numbers 범위가 어디까지인지 모르기 때문에 문자열 값도 numbers 범위에 포함됩니다. 이 부분은 사용할 때 주의하세요. :)

 

 

단일 표현식 함수

 

우리는 중괄호({}) 안에 함수가 수행될 로직들을 작성합니다. 하지만 중괄호를 사용하지 않고 바로 함수 결과를 반환할 수 있습니다.

 

//단일 표현식 함수

//타입 지정
fun getName():String = "개발이 취미인 사람"

//타입 추론
fun getName() = "개발이 취미인 사람"

 

위와 같이 코드를 작성하면 좀 더 간결하게 코딩을 할 수 있습니다.

 

응용을 한다면 아래와 같이 사용할 수 있습디다.

//when 조건 결과를 반환하는 단일 표현식 함수
fun getName(name:String):String = when(name){
    
    "개발자" -> "개발자야~~"
    "개발이 취미인 사람" -> "개발이 취미인 사람이야~~"
    else -> "난 뭐지...?"
    
}

//호출
fun main() {

    var name = getName("난 사실 요리사야~ :)")

    println(name)

    /**
      * 실행 결과
      *
      * 난 뭐지...?
      */
}

when 조건을 사용해서 특정 조건에 맞는 값을 연산해서 반환합니다. 위와 같이 단일 표현식 함수를 응용해서 사용할 수도 있습니다.

 

꼬리 재귀 함수

재귀 함수는 함수가 자신의 함수를 호출하는 함수이다. (getName함수가 getName 자신의 함수를 호출)

 

보통 재귀 함수를 호출할 때는 이전 함수에 변환 주소를 스택에 저장해야 하는 문제가 있기 때문에 StackOverflowError가 발생할 수 있다.

 

보통 이 문제를 해결하기 위해 반복문으로 문제를 해결하지만 사실 이 방법도 좋은 방법은 아니다.

 

코틀린 같은 최신 언어에서는 "꼬리 재귀 함수"라는 함수를 지원한다.

 

꼬리 재귀 함수 : 함수가 수행한 마지막 작업으로서 자신을 호출하는 특수한 종류의 재귀 함수이다. 즉, 함수의 마지막 작업 재귀를 수행한다.

 

코틀린에서 재귀 함수를 사용하려면 tailrec 한정자를 사용하면 됩니다.

 

//꼬리 재귀 함수 선언
tailrec fun checkCount(no: Int , count: Int){

    println("no 값은 무엇이야? : "+no)
    println("count 값은 무엇이야? : "+count)

    //no와 count 값이 같으면 if 그렇지 않다면 else 구문을 통해 자기 자신을 호출
    return if(no == count)
              println("if 실행")
           else checkCount(no - 1, count)
}

//호출
fun main() {

    checkCount(3, 1)

    /**
      * 실행 결과
      * 
      * no 값은 무엇이야? : 3
      * count 값은 무엇이야? : 1
      * no 값은 무엇이야? : 2
      * count 값은 무엇이야? : 1
      * no 값은 무엇이야? : 1
      * count 값은 무엇이야? : 1
      * if 실행
      */
}

 

보통 자바에서는 아래와 같이 사용된다.

 

public static final void tailrecPrint(int no, int count) {

     while (true) {

          System.out.println("no 값은 무엇이야? : " + no);
          System.out.println("count 값은 무엇이야? : " + count);

          if (no == count) {
              System.out.println("if문 실행");
                
              return;
          }
          --no;
     }
}

 

 

Parameter와 argument 기본 값 설정

파라미터 기본 값을 설정하는 방법은 "함수 파라미터에 기본 값을 설정"해서 사용하는 방법입니다.

//기본 파라미터 값이 있는 함수 (이름, 나이, 성별 [true 남성, false 여성])
fun userProfile(name:String, age: Int? = 20, gender:Boolean = true){

    println("이름은? : " + name)
    println("나이는? : " + age)
    println("성별은? : " + gender)

}

//호출
fun main() {

    userProfile("개발이 취미인 사람", null)
    /**
     * 실행 결과
     * 
     * 이름은? : 개발이 취미인 사람
     * 나이는? : null
     * 성별은? : true
     */
    
    userProfile("Ryan", 22)
    /**
     * 실행 결과
     * 
     * 이름은? : Ryan
     * 나이는? : 22
     * 성별은? : true
     */
    
    
    userProfile("개발자", 28, false)
    /**
     * 실행 결과
     * 
     * 이름은? : 개발자
     * 나이는? : 28
     * 성별은? : false
     */
}

 

아규먼트 기본 값을 설정하는 방법은 "함수를 호출할 때 파라미터 변수를 참조해 기본 값을 설정"해서 사용하는 방법입니다.

 

위에서 사용했던 userProfile함수를 예시를 들어보겠습니다.

 

 fun main(){
 
    userProfile("개발이 취미인 사람", gender = false)
    /**
     * 실행 결과
     *
     * 이름은? : 개발이 취미인 사람
     * 나이는? : 20
     * 성별은? : false
     */
}

 

gender 파라미터 속성에 기본 값을 false로 지정해서 함수를 호출하고 있습니다. 실행 결과를 보면 잘 반영된 걸 알 수 있습니다.

 

로컬 함수

코틀린에서는 함수 안에 함수를 선언해서 함수 내부적으로 사용할 수 있습니다.

 

로컬 함수는 어렵지 않기 때문에 예시는 생략하겠습니다.

 

이번 시간에는 코틀린에 함수에 대해 알아봤습니다. :)