Kotlin의 다양한 함수 다루기
확장함수
Kotlin은 Java와 100% 호환을 추구한다.
1
2
3
4
5
6
7
// 확장 함수
// String. -> String Class를 확장 -> 수신객체 타입
// 함수 안에서는 this를 통해 인스턴스 접근
// this -> 수신객체
fun String.lastChar(): Char {
return this[this.length - 1]
}
실제 사용 예시
1
2
val str = "ABC"
println(str.lastChar())
- 출력 : C
- 수신객체 타입을
String으로 설정 했기 때문에str에 바로lastChar메소드를 호출 가능
의문
확장함수가public이고 확장함수에서수신객체 클래스의private함수를 가져오면 캡슐화가 깨지는거 아닌가?- 그래서
확장함수는 클래스에 있는private또는protected멤버를 가져올 수 없다
- 그래서
- 맴버함수와 확장함수의 시그니처(
이름)가 같다면?
Java 메소드
1
2
3
4
public int nextYearAge() {
System.out.println("멤버 함수");
return this.age + 1;
}
Kotlin 메소드
1
2
3
4
fun Person.nextYearAge(): Int {
println("확장 함수")
return this.age + 1
}
위와 같이 Java의 맴버 함수와 Kotlin의 확장 함수 중 어떤 것을 호출 하나?
1
2
3
4
fun main() {
val person = Person("A", "B", 100)
person.nextYearAge()
}
- 출력 : 멤버 함수
확장 함수와멤버 함수중에서멤버 함수를 우선적으로 호출한다.- 확장 함수를 만들었지만, 다른 기능의 똑같은 멤버 함수가 생기면
오류 발생
확장 함수가 오버라이딩되는 경우
- 타입을 우선(
해당 변수의 현재 타입)으로 두고 호출하게 된다.
확장함수 요악
- 확장함수는 원본 클래스의
private,protected멤버 전근이 안된다. - 멤버함수, 확장함수 중 멤버함수에 우선권이 있다.
- 확장함수는 현재 타입을 기준으로 호출
Java에서 Kotlin의 함수를 사용하는 법
- Kotlin에 존자하는 함수를 정적 메소드를 부르는 것처럼 사용 가능
- ex).
StringUtilsKt.lastChar("ABC");처럼Kt를 붙인 정적 메소드로 호출 가능 - 확장함수는 확장프로퍼티와도 연결된다.
확장 프로퍼티
1
2
val String.lastChar: Char
get() = this[this.length - 1]
- 확장 프로퍼티의 원리 :
확장함수+custom getter와 동일
infix함수 (중위함수)
함수를 호출하는 새로운 방법
downTo,step(중위 함수 호출)- 변수,함수이름(argument)가 아니라,
변수 함수이름 argument(중위 함수 호출)
infix함수 예시
1
2
3
4
5
6
7
8
9
// 일반적인 함수
fun Int.add(other: Int): Int {
return this + other
}
// infix함수
infix fun Int.add2(other: Int): Int {
return this + other
}
infix는 멤버함수에도 붙일 수 있다.infix함수는 두가지 방법으로 호출 가능- 3.add2(4)
- 3 add2 4
inline함수
함수가 호출되는 대신, 함수를 호출한 지점에 함수 본문을 그대로 복붙하고 싶은 경우
inline함수 예시
1
2
3
inline fun Int.add(other: Int): Int {
return this + other
}
inline은 함수를 호출하는 것이 아닌, 로직 자체가 함수를 부르는 쪽에 복붙 된 것!- 함수를 파라미터로 전달할 때 오버헤드를 줄일 수 있기 때문에 사용
- 함수를 중첩해서 쓰는 경우, 함수가 함수를 부르는 과정이 반복되기 때문에
call chain에overhead발생
- 함수를 중첩해서 쓰는 경우, 함수가 함수를 부르는 과정이 반복되기 때문에
하지만, inline은 성능 측정과 함께 신중하게 사용해야 한다.
Kotlin라이브러리는 최적화가 잘되어 있기 때문에 적절하게inline이 붙어 있어 쓸일이 많지 않음.
지역함수
함수안에 함수를 선언할 수 있다.
중복되는 코드
1
2
3
4
5
6
7
8
9
10
11
fun createPerson(firstName: String, lastName: String): Person {
if (firstName.isEmpty()) {
throw IllegalArgumentException("firstName은 비어있을 수 없습니다 : $firstName")
}
if (lastName.isEmpty()) {
throw IllegalArgumentException("lastName은 비어있을 수 없습니다 : $lastName")
}
return Person(firstName, lastName, 1)
}
수정된 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
fun createPerson(firstName: String, lastName: String): Person {
fun validateName(name: String, fieldName: String) {
if (name.isEmpty()) {
throw IllegalArgumentException("${fieldName}은 비어있을 수 없습니다 : $name")
}
}
validateName(firstName, "firstName")
validateName(lastName, "lastName")
return Person(firstName, lastName, 1)
}
validateName이라는 함수를createPerson함수 안에 선언fun안에fun
함수를 추출하면 좋을 때, 함수 내에서만 사용하고 싶을 때 사용
- 단점 :
depth가 깊어 지기도 하고, 코드가 깔끔하지 않다. - 사실상 쓸 일이 별로 없을 듯
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.