[Kotlin] 3-2. 함수 정의와 호출
코틀린 공부 3일차
* 컬렉션, 문자열, 정규식을 다루기 위함 함수
* 이름 붙인 인자, 디폴트 파라미터 값, 중위 호출 문법
* 확장 함수와 확장 프로퍼티를 사용하여 자바 라이브러리 사용
* 최상위 및 로컬 함수와 프로퍼티를 사용해 코드 구조화
컬렉션 처리: 가변길이 인자, 중위함수 호출, 라이브러리 지원
자바 컬렉션 API 확장
3-1에서 코틀린은 자바의 컬렉션보다 더 많은 기능을 제공한다고 언급했다.
str.last()
numbers.max()
코틀린에서만 제공하는 last
와 max
함수는 모두 확장함수였던 것이다.
가변인자 함수: 인자의 개수가 달라질 수 있는 함수 정의
가변인자 함수를 알기위해서 우리는 코틀린에서의 listOf함수에 관심을 기울일 필요가 있다.
val list = listOf(2, 3, 5, 7, 11)
리스트를 생성하는 함수로 원하는 만큼 인자를 전달하여 생성할 수 있다. 여기서 중요한 것은 "원하는 만큼" 이다. 라이브러리에서 정의한 listOf함수를 보면 다음과 같다.
fun listOf<T>(vararg values: T) : List<T> { ... }
자바에서는 타입 뒤에 ...
를 붙이는 대신 코틀린에서는 파라미터 앞에 vararg
변경자를 붙인다.
스프레드 연산자에 대한 내용은 추후 필요시 작성하도록 하겠다.
값의 쌍 다루기: 중위 호출과 구조 분해 선언
중위 호출이라는 특별한 방식으로 호출한 사례를 소개한다.
val map = mapOf(1 to "one", 2 to "two")
1.to("one") -> to 메소드를 일반 방식으로 호출
1 to "one" -> to 메소드를 중위 호출 방식으로 호출
파라미터가 하나뿐인 일반, 확장함수에서 중위 호출을 사용할 수 있다. 중위 호출을 허용하고 싶으면 infix
변경자를 함수 선언 앞에 추가해야 한다. 이 부분도 자세한 내용은 추후 제대로 이해한 다음 작성하도록 하겠다.
코드 다듬기 : 로컬 함수와 확장
코드의 중복을 피하는 것은 개발자의 숙명이다. 코드의 중복을 피하기 위해 함수로 쪼개지만 클래스 내부에 작은 함수들이 너무 많아지고 오히려 코드를 이해하는데 어려움이 발생하기도 한다.
코틀린에서는 함수에서 추출한 함수를 원 함수 내부에 중첩시킬 수 있는 기능인 로컬함수가 있다. 잘 와 닿지 않을 것 같아서 예시코드를 준비했다. 아래 코드를 보자.
class User(val id: Int, val name: String, val address: String)
fun saveUser(user: User) {
if (user.name.isEmpty()) { --- (1)
throw IllegalArgumentException("Can't save user ${user.id} is empty Name")
}
if (user.address.isEmpty()) { --- (2)
throw IllegalArgumentException("Can't save user ${user.id} is empty Address")
}
// save user
}
(1)과 (2)의 코드가 중복된다는 것을 볼 수 있고 이를 함수화 해야한다. 이를 로컬함수로 바꾸어 보자.
class User(val id: Int, val name: String, val address: String)
fun saveUser(user: User) {
fun validate(user: User, value: String, fieldName: String) {
if(value.isEmpty()) {
throw IllegalArgumentException("Can't save user ${user.id} is "+
"empty $fieldName")
}
}
validate(user, user.name, "Name")
validate(user, user.address, "Address")
// save User
}
바꾸어보니 라인 수는 비슷할 지 몰라도 깔끔해졌을 뿐더러 추후 검증할 요소가 추가되더라도 쉽게 추가할 수 있다. (요소가 추가되면 될 수록 라인 수의 차이는 극명해질 것이다.)
그런데 validate
를 호출할 때마다 user
객체를 넘겨야하는 것은 불필요하다. → 로컬함수는 자신이 속한 바깥 함수의 모든 파라미터와 변수를 사용할 수 있다.
fun saveUser(user: User) {
... 생략 ...
validate(user.name, "Name")
validate(user.address, "Address")
// save User
}
그리고 이 예제를 개선하고 싶다면 User
의 확장함수를 validateBeforeSave
라는 이름으로 호출하면 더욱 깔끔해질 수 있다.
하지만, 일반적으로 한 단계만 함수를 중첩시키라고 권장한다. 함수의 깊이가 깊어지면 코드를 읽는데 상당히 어려워진다.
Author And Source
이 문제에 관하여([Kotlin] 3-2. 함수 정의와 호출), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@doingnow94/Kotlin-함수-정의와-호출-2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)