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로 스마트캐스트된다.이 방법으로, 분명한 캐스팅을 수동으로 하지 않고도 대부분의 경우 원하는 변수를 자동으로 사용할 수 있다.