component
함수componentN
함수
val (a, b) = p
--> val a = p.component1()
, val b = p.component2()
data
클래스의 주 생성자에 들어있는 프로퍼티에 대해서는 컴파일러가 자동으로 componentN
함수를 만들어 준다.
- 배열이나 컬렉션에는 Kotlin 표준 라이브러리에서 맨 앞의 다섯 원소에 대한 `componentN` 함수를 제공한다.
data class Point(val x: Int, val y: Int)
fun main(args: Array<String>) {
val p = Point(10, 20)
val (x, y) = p
println(x) // 10
println(y) // 20
}
data class NameComponents(
val name: String,
val extension: String)
fun splitFilename(fullName: String): NameComponents {
val (name, extension) = fullName.split('.', limit = 2)
return NameComponents(name, extension)
}
fun main(args: Array<String>) {
val (name, ext) = splitFilename("example.kt")
println(name) // example
println(ext) // kt
}
Map.Entry
에 대한 확장 함수로 component1
, component2
를 제공한다.fun printEntries(map: Map<String, String>) {
for ((key, value) in map) {
println("$key -> $value")
}
}
fun main(args: Array<String>) {
val map = mapOf("Oracle" to "Java", "JetBrains" to "Kotlin")
printEntries(map)
}
// Oracle -> Java
// JetBrains -> Kotlin
class Foo {
var p: Type by Delegate()
}
class Delegate {
operator fun getValue(object: Foo, property: KProperty<*>): Type {
// ...
}
operator fun setValue(object: Foo, property: KProperty<*>, newValue: Type) {
// ...
}
}
val x = c.prop
--> val x = delegateObj.getValue(c, kPropertyObj)
c.prop = x
--> delegateObj.setValue(c, kPropertyObj, x)
ReadOnlyProperty<R, T>
, ReadWriteProperty<R, T>
public interface ReadOnlyProperty<in R, out T> {
public operator fun getValue(thisRef: R, property: KProperty<*>): T
}
public interface ReadWriteProperty<in R, T> {
public operator fun getValue(thisRef: R, property: KProperty<*>): T
public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}
lazy
함수)class Email { /*...*/ }
fun loadEmails(person: Person): List<Email> {
println("Load emails for ${person.name}")
return listOf(/*...*/)
}
class Person(val name: String) {
val emails by lazy { loadEmails(this) }
}
fun main(args: Array<String>) {
val p = Person("Alice")
println(p.emails)
println(p.emails)
}
// Load emails for Alice
// []
// []
lazy
함수public fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
public interface Lazy<out T> {
public val value: T
public fun isInitialized(): Boolean
}
Expando Object
(확장 가능한 객체)class Person {
private val _attributes = hashMapOf<String, String>()
fun setAttribute(attrName: String, value: String) {
_attributes[attrName] = value
}
val name: String by _attributes
}
fun main(args: Array<String>) {
val p = Person()
val data = mapOf("name" to "Dmitry", "company" to "JetBrains")
for ((attrName, value) in data)
p.setAttribute(attrName, value)
println(p.name)
}
open class PropertyChangeAware {
protected val changeSupport = PropertyChangeSupport(this)
fun addPropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.addPropertyChangeListener(listener)
}
fun removePropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.removePropertyChangeListener(listener)
}
}
class Person(
val name: String, age: Int, salary: Int
) : PropertyChangeAware() {
var age: Int = age
set(newValue) {
val oldValue = field
field = newValue
changeSupport.firePropertyChange(
"age", oldValue, newValue)
}
var salary: Int = salary
set(newValue) {
val oldValue = field
field = newValue
changeSupport.firePropertyChange(
"salary", oldValue, newValue)
}
}
fun main(args: Array<String>) {
val p = Person("Dmitry", 34, 2000)
p.addPropertyChangeListener(
PropertyChangeListener { event ->
println("Property ${event.propertyName} changed " +
"from ${event.oldValue} to ${event.newValue}")
}
)
p.age = 35
p.salary = 2100
}
open class PropertyChangeAware {
protected val changeSupport = PropertyChangeSupport(this)
fun addPropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.addPropertyChangeListener(listener)
}
fun removePropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.removePropertyChangeListener(listener)
}
}
class ObservableProperty(
var propValue: Int, val changeSupport: PropertyChangeSupport
) {
operator fun getValue(p: Person, prop: KProperty<*>): Int = propValue
operator fun setValue(p: Person, prop: KProperty<*>, newValue: Int) {
val oldValue = propValue
propValue = newValue
changeSupport.firePropertyChange(prop.name, oldValue, newValue)
}
}
class Person(
val name: String, age: Int, salary: Int
) : PropertyChangeAware() {
var age: Int by ObservableProperty(age, changeSupport)
var salary: Int by ObservableProperty(salary, changeSupport)
}
fun main(args: Array<String>) {
val p = Person("Dmitry", 34, 2000)
p.addPropertyChangeListener(
PropertyChangeListener { event ->
println("Property ${event.propertyName} changed " +
"from ${event.oldValue} to ${event.newValue}")
}
)
p.age = 35
p.salary = 2100
}
Delegates.observable
을 통해 구현 (코틀린 표준 라이브러리)open class PropertyChangeAware {
protected val changeSupport = PropertyChangeSupport(this)
fun addPropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.addPropertyChangeListener(listener)
}
fun removePropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.removePropertyChangeListener(listener)
}
}
class Person(
val name: String, age: Int, salary: Int
) : PropertyChangeAware() {
private val observer = {
prop: KProperty<*>, oldValue: Int, newValue: Int ->
changeSupport.firePropertyChange(prop.name, oldValue, newValue)
}
var age: Int by Delegates.observable(age, observer)
var salary: Int by Delegates.observable(salary, observer)
}
fun main(args: Array<String>) {
val p = Person("Dmitry", 34, 2000)
p.addPropertyChangeListener(
PropertyChangeListener { event ->
println("Property ${event.propertyName} changed " +
"from ${event.oldValue} to ${event.newValue}")
}
)
p.age = 35
p.salary = 2100
}
equals
, compareTo
get
, set
, contains
rangeTo
, iterator
componentN
by
lazy
Delegates.obeservable