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 라이센스를 따릅니다.