2022-03-16 작성완료
대부분의 다른 프로그래밍 언어들과 같이(java, c++ 등), 코틀린은 정의된 순서에 따라 메서드와 생성자에 아규먼트를 전달할 수 있다. 코틀린은 또한 더 명확한 호출을 허용하고 아규먼트 순서에 따른 실수를 피할 수 있도록 named arguments를 지원한다. 그러한(아규먼트 순서로 인한) 실수는 컴파일러에 의해 탐지되지 않으므로 발견하기 힘들다. 예를 들어 두 연속된 아규먼트가 같은 타입일 때 그렇다.
fun format(userName: String, domain: String) = "$userName@$domain"
fun main() {
println(format("mario", "example.com")) // 1
println(format("domain.com", "username")) // 2
println(format(userName = "foo", domain = "bar.com")) // 3
println(format(domain = "frog.com", userName = "pepe")) // 4
}
String templates는 변수 참조 및 표현식을 문자열에 포함시킬 수 있도록 한다. 스트링의 값이 요구될 때 (예: println
) 모든 참조와 표현식들은 실제 값으로 대체된다.
val greeting = "Kotliner"
println("Hello $greeting") // 1
println("Hello ${greeting.toUpperCase()}") // 2
$
로 시작한다.$
로 시작하고 중괄호로 에워싸인다.Destructuring declaration 구문은 매우 편리할 수 있다. 특히 멤버에 접근하기 위한 인스턴스가 필요할 때 편리하다. 이것은 지정된 이름 없이 인스턴스를 정의할 수 있게 해 주며, 그로 인해 코드 몇 줄을 줄일 수 있다.
val (x, y, z) = arrayOf(5, 10, 15) // 1
val map = mapOf("Alice" to 21, "Bob" to 25)
for ((name, age) in map) { // 2
println("$name is $age years old")
}
val (min, max) = findMinMax(listOf(100, 90, 50, 98, 76, 83)) // 3
Array
구조 분해. 왼편 변수의 수는 오른편 아규먼트의 수와 같아야 한다. name
과 age
변수는 맵의 키와 값에 매핑되었다.Pair
와 Triples
타입도 구조 분해를 지원한다. 심지어 함수의 리턴값일 경우에도 구조 분해 가능하다. data class User(val username: String, val email: String) // 1
fun getUser() = User("Mary", "mary@somewhere.com")
fun main() {
val user = getUser()
val (username, email) = user // 2
println(username == user.component1()) // 3
val (_, emailAddress) = getUser() // 4
}
component1()
과 component2()
메서드를 정의한다. 이 메서드들은 구조분해 중에 호출될 것이다._
)를 사용한다. 이것은 사용하지 않는 변수를 나타내는 컴파일러 힌트를 피하게 한다.class Pair<K, V>(val first: K, val second: V) { // 1
operator fun component1(): K {
return first
}
operator fun component2(): V {
return second
}
}
fun main() {
val (num, name) = Pair(1, "one") // 2
println("num = $num, name = $name")
}
component1()
과 component2()
메서드를 가진 커스텀 Pair
클래스를 정의한다.Pair
와 동일한 방법으로 구조분해한다.코틀린 컴파일러는 대부분의 경우 타입 캐스트를 자동으로 수행할 수 있을 정도로 똑똑하다. 타입 캐스트가 가능한 경우는 다음을 포함한다:
import java.time.LocalDate
import java.time.chrono.ChronoLocalDate
fun main() {
val date: ChronoLocalDate? = LocalDate.now() // 1
if (date != null) {
println(date.isLeapYear) // 2
}
if (date != null && date.isLeapYear) { // 3
println("It's a leap year!")
}
if (date == null || !date.isLeapYear) { // 4
println("There's no Feb 29 this year...")
}
if (date is LocalDate) {
val month = date.monthValue // 5
println(month)
}
}
isLeapYear
에 직접 접근할 수 있게 한다.LocalDate
로 스마트캐스트된다.이 방법으로, 분명한 캐스팅을 수동으로 하지 않고도 대부분의 경우 원하는 변수를 자동으로 사용할 수 있다.