코틀린 (Kotlin) 로컬 함수

코틀린 로컬 함수

코틀린에서 중복 코드를 간단하게 줄일 수 있는 방법으로 로컬 함수를 사용할 수 있습니다.
로컬 함수는 함수 내부에 함수를 중첩해서 만들 수 있습니다.

로컬 함수는 바깥 함수의 파라미터 변수에 접근할 수 있습니다.
그리고 로컬 함수에 파라미터를 전달하여 사용할 수도 있습니다.

class SaveUser {

    /**
     * 로컬 함수
     */
    fun validateUser(user: User) {
        //로컬 함수는 바깥 함수의 파라미터와 변수에 접근 할 수 있다
        fun validate(value: String, fieldName: String) {
            if (value.isEmpty()) {
                throw IllegalArgumentException(
                    "Can't save user ${user.id}: " +
                            "empty $fieldName" + "value=$value")
            }
        }

        //예외처리로직을 로컬 함수로 공통화 시킬 수 있음
        validate(user.name, "Name")
        validate(user.address, "Address")
    }
}

로컬 함수를 사용해서 중복된 코드를 줄일 수 있습니다.
그리고 공통으로 사용하기 위해 작게 쪼게진 함수들이 많은 경우 로컬 함수를 사용해서 공통 처리를 하는데 도움이 될 수 있습니다.

그러나 SaveUser 클래스에 있는 validateUser() 함수를 다른 클래스에서 사용하고 싶은 경우 validateUser() 함수를 그대로 복사 붙여넣기 하거나 User 클래스 내부에 함수를 이동시켜 공통으로 사용할 수 있습니다.

validateUser() 함수를 User 클래스에 넣고 싶지 않은 경우 확장 함수를 이용하면 중복 코드와 User 클래스를 간단하게 하면서 공통 처리가 가능합니다.

확장 함수와 로컬 함수

로컬 함수로 코드 중복을 줄였다면, 확장 함수를 사용해서 더 효율적인 코드를 만들 수 있습니다.

확장 함수를 이용해서 User 클래스에 validateUser() 함수를 추가하지 않고 필요한 곳에서 user.validateUser() 를 호출해서 공통화할 수 있습니다.

/**
  * 확장 함수 내 로컬 함수
  */
fun User.validateUser() {
    fun validate(value: String, fieldName: String) {
        if (value.isEmpty()) {
            throw IllegalArgumentException(
                //$id 의경우 확장함수이기때문에 User 프로퍼티에 직접 접근 가능
                "Can't save user $id: empty $fieldName")
        }
    }

    validate(name, "Name") //확장 함수에서는 public 멤버 변수에 접근 가능
    validate(address, "Address") //확장 함수에서는 public 멤버 변수에 접근 가능
}

그리고 확장 함수를 사용하면 위에 로컬 함수에서 사용했던 validate(user.name, "Name") 에서 user.name 을 호출하던 것을 name 으로 직접 호출 할 수 있습니다.

val user = User(1, "", "")
user.validateUser() //확장 함수 호출

함수 안에 확장 함수를 로컬 함수로 정의할 수도 있습니다.
그러나 함수의 깊이가 깊어지면 코드 읽기가 어렵기때문에 한 단계만 함수를 중첩하는 것을 권장합니다.

fun saveUser(user: User) {
    fun User.validateBeforeSave() { //많은 중첩 대신 한 단계만 중첩하는것을 권장
        fun validate(value: String, fieldName: String) {
            if (value.isEmpty()) {
                throw IllegalArgumentException(
                    "Can't save user $id: empty $fieldName")
            }
        }
        validate(name, "Name")
        validate(address, "Address")
    }
    user.validateBeforeSave()
}


*개인적으로 코틀린을 공부하면서 정리한 자료입니다. 수정 사항 및 이슈가 있는 경우 메일 부탁드립니다.

댓글

이 블로그의 인기 게시물

코틀린 (Kotlin) filter, map, all, any, count, find, groupBy, flatMap 함수 정리

코틀린 (Kotlin) 인터페이스 정리

코틀린 (Kotlin) object 키워드와 동반 객체 정리