728x90
반응형
✅ 코틀린에서 컬렉션 만들기
- 코틀린의 컬렉션은 자바 컬렉션 구조를 확장해 구현되었음
- 그렇기 때문에 자바에서 코틀린 함수를 호출하거나 코틀린에서 자바 함수를 호출할 때 자바와 코틀린 컬렉션을 서로 변환할 필요가 없음
- 코틀린 컬렉션은 자바 컬렉션과 똑같은 클래스
- 하지만 코틀린에서는 자바보다 더 많은 기능을 사용할 수 있음
- ex) 리스트의 마지막 원소를 가져오거나 수로 이뤄진 컬렉션에서 최댓값을 찾을 수 있음
val strings = listOf("first", "second", "third")
println(strings.last()) // third
val numbers = setOf(1, 14, 2)
println(numbers.max()) // 14
- 코틀린의 컬렉션의 종류는 List, Set, Map 등이 있으며 자바와는 다르게 불변형(Immutable)과 가변형(mutable)으로 나뉨
- 자바에서는 오로지 가변형 컬렉션만 취급되기 때문에 자바와 상호작용하는 코드에서는 사용에 주의해야 함
컬렉션 | 불변형(읽기 전용) | 가변형 |
List | listOf | mutableListOf, arrayListOf |
Set | setOf | mutableSetOf, hashSetOf, ... |
Map | mapOf | mutableMapOf, hashMapOf,... |
✅ 함수를 호출하기 쉽게 만들기
- 자바 컬렉션에는 디폴트 toString 구현이 들어있음
- 하지만 그 디폴트 toString의 출력 형식은 고정돼 있고 우리에게 필요한 형식이 아닐 수 있음
val list = listOf(1, 2, 3)
println(list) // toString() 호출
// [1, 2, 3]
- 디폴트 구현과 달리 (1; 2; 3)처럼 원소 사이를 세미콜론으로 구분하고 괄호로 리스트를 둘러싸고 싶다면 어떻게 해야 하나?
- 코틀린에서는 이런 요구사항을 처리할 수 있는 함수가 표준 라이브러리에 들어있음
// joinToString() 함수의 초기 구현
fun <T> joinToString(
collection: Collection<T>,
separator: String,
prefix: String,
postfix: String
) : String {
val result = StringBuilder(prefix)
for((index, element) in collection.withIndex()) {
if (index > 0) result.append(separator) // 첫 원소 앞에는 구분자를 붙이면 안 됨
result.append(element)
}
result.append(postfix)
return result.toString()
}
// 위 함수는 제네릭으로 어떤 타입의 값을 원소로 하는 컬렉션이든 처리 가능
val list = listOf(1,2,3)
print(joinToString(list, "; ", "(", ")") // (1; 2; 3)
📌 이름 붙인 인자
함수 호출할 때 가독성이 떨어지는데 이를 해결하기 위해서는??
joinToString(collection, " ", " ", ".")
- 위와 같이 인자로 전달한 각 문자열이 어떤 역할을 하는지 구분하기는 어려운 일
- 자바에서는 파라미터 이름을 주석에 넣으라고 요구되기도 함
joinToString(collection, /* separator */ " ", /* prefix */ " ", /* postfix */ ".");
- 하지만 코틀린에서는 함수를 호출할 때 함수에 전달하는 인자 중 일부(또는 전부)의 이름을 명시할 수 있음
- 호출 시 인자 중 어느 하나라도 이름을 명시하고 나면 혼동을 막기 위해 그 뒤에 오는 모든 인자는 이름을 꼭 명시하는 것이 좋음
joinToString(collection, separator = " ", prefix = " ", postfix = ".")
- 이름 붙인 인자는 디폴트 파라미터 값과 사용할 때 쓸모가 많음
📌 디폴트 파라미터 값
- 자바에서는 일부 클래스에서 오버로딩한 메서드가 너무 많아진다는 문제가 있을 수 있음
- 파라미터 이름과 타입이 계속 반복되거나, 인자 중 일부가 생략된 오버로드 함수를 호출할 때 어떤 함수가 불릴지 모호간 경우가 생길 수 있음
- 하지만 코틀린에서는 함수 선언에서 파라미터의 디폴트 값을 지정할 수 있어 이러한 오버로드의 문제 중 상다수를 피할 수 있음
- 대부분의 경우 아무 접두사나 접미사 없이 콤마로 원소를 구분
// 디폴트 파라미터 값을 사용해 joinToString() 정의하기
fun <T> joinToString (
collection : Collection<T>,
separator : String = ", ", // 디폴트
prfix : String = "", // 값이 지정된
postfix : String = "" // 파라미터들
) : String
- 위와 같이 사용하게 되면 함수를 호출할 때 모든 인자를 쓸 수도 있고, 일부를 생략할 수도 있음
joinToString(list, ", ", "", "") // 1, 2, 3
joinToString(list) // 1, 2, 3
joinToString(list, "; ") // 1; 2; 3
- 함수를 사용할 때 디폴트 파라미터 값은 함수를 호출하는 쪽이 아닌 함수 선언 쪽에서 지정된다는 사실을 기억해야 함
- 따라서 어떤 클래스 안에 정의된 함수의 디폴트 값을 바꾸고 그 클래스가 포함된 파일을 재컴파일하면 그 함수를 호출하는 코드 중에 값을 지정하지 않은 모든 인자는 자동으로 바뀐 디폴트 값을 적용받음
📌 정적인 유틸리티 클래스 없애기 : 최상위 함수와 프로퍼티
- 최상위 함수 : 클래스 내부가 아닌 클래스 외부에 정의하는 함수
- 최상위 프로퍼티 : 클래스 내부가 아닌 클래스 외부에 정의하는 프로퍼티(객체 지향 언어에서는 어떤 데이터를 클래스 밖에 위치시켜야 하는 경우가 있으며 유용하게 쓰일 때가 있음. 이때, 상수를 최상위 프로퍼티로 선언하는 경우가 많음)
- 객체지향 언어인 자바에서는 모든 코드를 클래스의 메서드로 작성해 멤버 메소드, 프로퍼티로 존재하도록 작성함
- 이런 구조는 잘 작동하기는 하지만, 실전에서는 어느 한 클래스에 포함시키기 어려운 코드가 많이 생길 수 있음
- 그래도 클래스를 생성해 내부에 넣게 되면 코드의 길이가 적은 클래스가 여럿 생겨나게 될 수 있음
- 이런 문제로 자바 개발자들은 Util 클래스와 같이 정적 메소드들을 한 곳에 모아두는 역할을 하는 클래스를 만들기도 하였음
- 이런 문제로 자바 개발자들은 Util 클래스와 같이 정적 메소드들을 한 곳에 모아두는 역할을 하는 클래스를 만들기도 하였음
- 하지만 코틀린에서는 이런 무의미한 클래스를 만들 필요가 없음
- 대신 함수를 직접 소스 파일의 최상위 수준, 모든 다른 클래스의 밖에 위치시키면 됨(최상위 함수)
- 그런 함수들은 여전히 그 파일의 맨 앞에 정의된 패키지의 멤버 함수이기 때문에 다른 패키지에서 그 함수를 사용하고 싶은 경우 해당 패키지를 임포트 하여 사용할 수 있으며 인스턴스가 필요하지 않음
- 코틀린 파일에서 정의한 최상위 함수는 자바 파일에서도 호출할 수 있음
// joinToString() 함수를 최상위 함수로 선언하기
package strings
fun joinToString(...) : String ( ... )
- 함수와 마찬가지로 프로퍼티도 파일의 최상위 수준에 놓을 수 있음
- 흔하게 사용하지는 않지만 가끔 유용하게 사용할 수 있음
- ex) 어떤 연산을 수생한 횟수를 저장하는 var 프로퍼티
var opCount = 0
fun performOperation() {
opCount ++
// ...
}
fun reportOperationCount() {
println("Operation performed $opCount times") // 최상위 프로퍼티의 값을 읽음
}
728x90
반응형
'Studying > Kotlin' 카테고리의 다른 글
[Kotlin In Action] 3장. 함수 정의와 호출(3) - 컬렉션 처리 (0) | 2023.05.08 |
---|---|
[Kotlin In Action] 3장. 함수 정의와 호출(2) - 확장 함수와 확장 프로퍼티 (0) | 2023.05.02 |
[Kotlin In Action] 2장. 코틀린 기초(4) - 코틀린의 예외 처리 (0) | 2023.04.24 |
[Kotlin In Action] 2장. 코틀린 기초(3) - while과 for 루프 (0) | 2023.04.24 |
[Kotlin In Action] 2장. 코틀린 기초(2) - enum과 when (0) | 2023.04.24 |