์ฌ์ฌ์ฉ์ ์ํ ๊ณผ๋ํ ์ ์ฐ์ฑ
๋ค์ํ ํ์ ์ ๋์ผํ ๋ก์ง์ ์ ์ฉํ๊ธฐ ์ํด ์ฝ๋ ์ฌ์ฌ์ฉ์ ๊ณผ๋ํ๊ฒ ํ๋ ค๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ถ Any๋ก ๋ฐ๋ ๊ฒ์ด ๋ํ์ ์ธ ์์์ ๋๋ค.
open class Car
class K3 : Car()
class Avante : Car()
//“์ฐจ์ ๋ํ ์ค๋ช
์” ํจ์
fun getInstruction(car: Array<Any>) {
println("car = ${car.size}")
}
๋ง์ด ๊ทน๋จ์ ์ธ ์์ ์ด๊ธฐ๋ ํฉ๋๋ค..
open class Fruit
class Apple : Fruit()
fun main() {
val k3 = K3("k3", "๊ธฐ์")
val avante = Avante("์๋ฐ๋ผ", "ํ๋")
val fruits: Array<Apple> = arrayOf(Apple())
getInstruction(fruits) // Type mismatch ์๋ฌ
}
getIstruction ํจ์๋ “์ฐจ์ ๋ํ ์ค๋ช ์” ์๋๋ก ๋ง๋ ๊ฒ์ด์ง๋ง ์ด๋ฅผ ๋ชจ๋ฅด๊ณ ๊ณผ์ผ์ธ Apple ํ์ ์ ๊ฐ์ง Array๋ฅผ ์ง์ด ๋ฃ์ ์ ์์ต๋๋ค. ์ธํ ๋ฆฌ์ ์ด๊ฐ ์๋ ๋๋ํด์ ๋ฏธ๋ฆฌ ์ด๋ฐ ์๋ฌ๋ฅผ ์ก์ ๋ด๊ธด ํ์ง๋ง ์ฌ์ฌ์ฉ์ ์ํด Any๋ฅผ ์์ฃผ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ ์์ ์ฑ์ ์ ํ์ํฌ ์๊ฐ ์์ต๋๋ค. ⇒ ์ ๋ค๋ฆญ์ ์ฌ์ฉํ๋ ์ด์
์ ๋ค๋ฆญ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ถ๋ณ์ฑ
์๋ฐ์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๋ค๋ฆญ์ ํ์ ๋ถ๋ณ์ฑ์ ๊ฐ์ํ์ต๋๋ค. ์ ๋ค๋ฆญ ํจ์๊ฐ ํ๋ผ๋ฏธํฐ ํ์ T ๋ฅผ ๋ฐ๋๋ค๋ฉด T ์ ๋ถ๋ชจ ํด๋์ค๋ ์์ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ์ต๋๋ค. ์ฆ, ํ์ ์ด ์ ํํ ์ผ์นํด์ผ๋ง ํ์ต๋๋ค.
์ฝ๋์ ์ ์ฝ์ ํฌ๊ฒ ๊ฑธ์๋ก ์์ ์ฑ์ ๋์์ง๋ค๊ณ ์๊ฐํฉ๋๋ค.
open class Car
class K3 : Car()
class Avante : Car()
fun getInstruction(car: Array<Car>) {
println("car = ${car.size}")
}
fun main() {
val cars = arrayOf(K3())
getInstruction(cars)// Type mismatch ์๋ฌ
}
์ ๋ค๋ฆญ์ ๋ถ๋ณ์ฑ์ด๋ฏ๋ก ๋ถ๋ชจ ํด๋์ค๋ , ์์ ํด๋์ค๋ ํ์ ์ด ์ ํํ ์ผ์นํ์ง ์์ผ๋ฉด ์๋ฌ๋ฅผ ๋ฐ์์ํต๋๋ค.
fun getInstruction(car: List<Car>) {
println("car = ${car.size}")
}
fun main() {
val cars = listOf(K3())
getInstruction(cars)
}
ํ์ง๋ง car: Array<Car> ๋ฅผ car: List<Car> ๋ก ๋ฐ๊ฟ์ค๋ค๋ฉด ์ ์ฝ๋๋ ๋ฌธ์ ์์ด ์ปดํ์ผ์ด ๋ฉ๋๋ค.
์ ๋ค๋ฆญ์ ๊ธฐ๋ณธ์ ์ด๊ณ ๋ถ๋ณ์ฑ์ด๊ณ , ํ์ ์ด ์ ํ์ธ ์ผ์นํด์ผ ๋ฐ์ ์ ์๋๋ฐ ์ Array<T>๋ ์๋๊ณ , List<T>๋ ๋๋ ๊ฑธ๊น์?
Array<T> ๋ ๊ฐ๋ณ(mutable) ์ด์ง๋ง List<T> ๋ ๋ถ๋ณ(immutable) ์ ๋๋ค. Array ์ ์์ดํ ์ ๋ณ๊ฒฝํ ์ ์์ง๋ง List ์ ์์ดํ ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ๋ณ๊ฒฝํ ์ ์๋ค๋ ์ ๋๋ฌธ์ ์์ ์ฑ์ด ๋ณด์ฅ๋๋ค ์๊ฐํ์ฌ getInstruction(car: List<Car>)์์ ๋ฐ์ ์ ์์ต๋๋ค.
๋ํ Array<T> ๋ class Array<T> ๋ก ์ ์๋์ด ์๊ณ , List<T> ๋ interface List<out E> ๋ก ์ ์๋์ด์๋๋ฐ, ๋ฐ๋ก List ์ ๋ค๋ฆญ ํ์ ์ ์ฌ์ฉ๋ out ๋๋ถ์ ๋๋ค.
<out T> ์ผ๋ก ๊ณต๋ณ์ฑ(covariance) ์ฌ์ฉํ๊ธฐ
fun copyFromTo(from: Array<Car>, to: Array<Car>){
for (i in from.indices){
to[i] = from[i]
}
}
fun main() {
val cars1 = Array<Car>(3) { _ -> Car() }
val cars2 = Array<Car>(3) { _ -> Car() }
copyFromTo(cars1, cars2)
}
copyFromTo() ํจ์๋ from ๋ฐฐ์ด์ ๊ฐ์ฒด๋ฅผ ์ํํ๋ฉด์ to ๋ฐฐ์ด๋ก ๊ฐ์ ๋ฃ์ด์ฃผ๋ ํจ์์ ๋๋ค.
์ด๋ ์ ๋ฌ ๋ฐ์ ๋ ๋ฐฐ์ด์ ํฌ๊ธฐ๋ ๋์ผํ๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
์์ ๊ฐ์ด ๊ตฌํ ํ ๊ฒฝ์ฐ์๋ ๋ณ ๋ฌธ์ ์์ด ๋์ํฉ๋๋ค. ์๋ํ๋ฉด copyFromTo() ํจ์์ ํ๋ผ๋ฏธํฐ๋ก Car ํ์ ์ ๋ฐฐ์ด๋ก ์ ์ํ๊ณ , ๊ทธ์ ๋ง์ถฐ ๋๊ฒจ์คฌ๊ธฐ ๋๋ฌธ์ ๋๋ค.(๋ถ๋ณ์ฑ)
fun main() {
val cars1 = Array<K3>(3) { _ -> K3() }
val cars2 = Array<Car>(3) { _ -> Car() }
copyFromTo(cars1, cars2) // type mismatch
}
ํ์ง๋ง ์ ์ฝ๋๋ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค. ์๋ ์ฝํ๋ฆฐ์ Array<Car> ์๋ฆฌ์ Array<K3> ๋ฅผ ์ ๋ฌํ์ง ๋ชปํ๋๋ก ๋ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
(๋ถ๋ณ์ฑ ์๋ฐฐ)
์ด๋ out ์ ์ฌ์ฉํ๋ฉด type mismatch ์ ํด๊ฒฐํ ์ ์์ต๋๋ค.(๊ณต๋ณ์ฑ ์ฌ์ฉ)
fun copyFromTo(from: Array<out Car>, to: Array<Car>){
for (i in from.indices){
to[i] = from[i]
}
}
์ด๋ ์ฃผ์ ํ ์ ์ด ์์ต๋๋ค. ์๋์ ๊ฐ์ ์ฝ๋๊ฐ ๊ทธ ๊ฒฝ์ฐ์ ๋๋ค.
fun copyFromTo(from: Array<out Car>, to: Array<Car>) {
for (i in from.indices) {
from[i] = Car()
}
from[0] = K3() // ์!
}
์ธํ ๋ฆฌ์ ์ด๋ ์ด๋ ๊ฒ ๋งํ๊ณ ์์ต๋๋ค.
“์ ๋ค๋ฆญ ํ์ ์ out ํค์๋๋ฅผ ๋ฃ์ด์ค from์ Nothing ํ์ ์ write ํด์ฃผ๊ธธ ์ํ๋๋ฐ, ์ K3 ํ์ ์ writeํ๋๊ฐ?”
์ด๋ from์ด <out T> ์ ๋ค๋ฆญ ํ์ ์ ์ฐ๋ฉด์ ๊ณต๋ณ์ฑ์ ๊ฐ์ง๊ฒ ๋์ด ์๊ธด ๋ฌธ์ ์ธ๋ฐ,
๊ณต๋ณ์ฑ์ ๊ฐ์ง๊ฒ ๋๋ฉด ๊ฐ์ ๋ํ read๋ง ๊ฐ๋ฅํ๊ณ , write์ด ๋ถ๊ฐ๋ฅํด์ง๋๋ค.
Read๋ง ๊ฐ๋ฅํ๊ณ Write๋ ๋ถ๊ฐ๋ฅํ ์ด์
read๋ง ๊ฐ๋ฅํ ์ด์
Array<out Car> ํ์ ์ธ from์ ๋ถ๋ชจ๊ฐ Car์ธ ๊ฒ์ ์ปดํ์ผ๋ฌ๊ฐ ์ธ์งํ๊ณ ์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด from์ ๊ฐ์ read ํ ๋์๋ Car, K3, Avante ์ค ํ๋์ผ ๊ฒ๋ ์ ๊ฒ์ด๋ฉฐ, ์ด๋ ๋ชจ๋๋ฅผ ํฌํจํ๋ Car๋ก ํ ๋น ํด ์ค ์ ์์ผ๋ฏ๋ก read๋ฅผ ํ ๋์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.
write๊ฐ ๋ถ๊ฐ๋ฅํ ์ด์
๊ทธ๋ฌ๋ write์ ๊ฒฝ์ฐ์๋ ์ข ๋ค๋ฆ ๋๋ค. ๊ณต๋ณ์ฑ์ ์ฌ์ฉํ from์๊ฒ ์ค์ ๋ก๋ Array<K3>์ ๋๊ฒจ์คฌ์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ฉ์๋์์ from์ Array<out T>๋ก ์ ์ธ๋์ด ์์ผ๋ฏ๋ก, ์ค์ from์ด Array<Car>์ธ์ง, Array<K3>์ธ์ง, Array<Avante>์ธ์ง ๋ชจ๋ฆ ๋๋ค. from์ ์ค์ Array Type์ ๋ชจ๋ฅด๋ ๋ฉ์๋๊ฐ ํจ๋ถ๋ก ๊ฐ์ write ํ ์ ์์ผ๋ฏ๋ก ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ฆ, out ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ณต๋ณ์ฑ์ ์ฌ์ฉํ ๊ฒฝ์ฐ์๋ ์ฝ๊ธฐ๋ง(read-only) ์ฌ์ฉ ๊ฐ๋ฅํ๋ค๊ณ ๋ณผ ์ ์๋ ๊ฒ์ด์ฃ .
*๊ณต๋ณ์ฑ : A ํ์ ์ด B ํ์ ์ ์๋ธ ํ์ ์ผ ๋, C<A>๋ C<B>์ ์๋ธํ์ ์ ๋๋ค.
read-only ๊ฐ ์๋ค๋ฉด ๋ฐ๋๋ก ์ฐ๊ธฐ ์ ์ฉ(write-only) ๋ ์์ต๋๋ค.
<in T> ์ผ๋ก ๋ฐ๊ณต๋ณ์ฑ(contravariance) ์ฌ์ฉํ๊ธฐ
๊ณต๋ณ์ฑ์ ์ฌ์ฉํ ๋ ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ๋ค๊ณ ํด์ out์ ์ฌ์ฉํ์๋๋ฐ, ๋ฐ๊ณต๋ณ์ฑ์์๋ ๋ฐ๋๋ก ์ฐ๊ธฐ๋ง ๊ฐ๋ฅํ์ฌ in์ ์ฌ์ฉํฉ๋๋ค.
fun copyFromTo(from: Array<out Car>, to: Array<Car>){
for (i in from.indices){
to[i] = from[i]
}
}
T ๊ฐ Car ํ์ ์ด๊ฑฐ๋ Car ์ ํ์ ํด๋์ค๋ผ๋ฉด ์๋ฌด Array<T> ๋ก๋ถํฐ ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํ๋ ๊ฒ์ ์ ์์ ์ ๋๋ค. ๊ณต๋ณ์ฑ์ ์ฝํ๋ฆฐ์ด from ํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ฐํ๋๋ก ํ๋ ๊ฒ ์์ ํ๋ค๋ ๊ฒ์ ๋ณด์ฅํด์ค๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ฒ์๋ to ํ๋ผ๋ฏธํฐ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. to ํ๋ผ๋ฏธํฐ์ ํ์ ์ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ Array<Car> ์ ๋๋ค.
to ํ๋ผ๋ฏธํฐ์ Array<Car> ์ ์ ๋ฌํ๋ค๋ฉด ๋ฌธ์ ๊ฐ ์๊ฒ ์ง๋ง, Car ์ ๋ถ๋ชจ ํด๋์ค๋ฅผ ์ ๋ฌํ๊ณ ์ถ์ ๋๋ ์ด๋จ๊น์?
์ด๋ in์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
fun main() {
val cars1 = Array<K3>(3) { _ -> K3() }
val cars2 = Array<Any>(3) { _ -> Any() }
copyFromTo(cars1, cars2)// type mismatch
}
fun copyFromTo(from: Array<out Car>, to: Array<Car>){
for (i in from.indices){
to[i] = from[i]
}
}
์ ์ฝ๋์ฒ๋ผ ํ๊ฒ ๋๋ฉด ์ ๋ค๋ฆญ์ ๋ถ๊ณต๋ณ์ฑ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
fun copyFromTo(from: Array<out Car>, to: Array<in Car>){
for (i in from.indices){
to[i] = from[i]
}
}
๋ฐ๋ผ์ in ์ ๋ถ์ด์ฃผ๊ฒ ๋๋ฉด ์ด๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
to ํ๋ผ๋ฏธํฐ์ ์๋ ์์ฒญ๋ ํ์ ์ด๋ ๊ทธ ํ์ ์ ์กฐ์ ํ์ ์ด ๊ฐ๋ฅํ๊ฒ ํ๋ ๊ถํ(๋ฐ๊ณต๋ณ์ฑ)์ ์์ฒญํ ๊ฒ์ ๋๋ค.
ํ์ง๋ง ์๋ ์ฝ๋๋ ์๋ฌ๋ฅผ ๋ฐ์์ํต๋๋ค. ์์์ ๋ง์ ๋๋ฆฐ๊ฒ์ฒ๋ผ ๋ฐ๊ณต๋ณ์ฑ์ Write๋ง ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
fun copyFromTo(from: Array<out Car>, to: Array<in Car>){
for (i in from.indices){
to[i] = from[i]
}
var any: Car = to[0]
}
์ด์ ๋ ๊ฐ๋จํฉ๋๋ค. ๋ฐ๊ณต๋ณ์ฑ์ผ๋ก ์ธํด ์ ๋ค๋ฆญ ํ์ ๋๋ ์กฐ์ ํ์ ์ ๊ฐ๋ฅํ๊ฒ ํ์์ผ๋ฏ๋ก,
์ ๋ค๋ฆญ ํ์ ์ผ๋ก ํด๋น ๊ฐ์ read ํ ๋ ํด๋น ๊ฐ์ ํ์ ์ด ์ ๋ค๋ฆญ ํ์ ์ ์กฐ์ ํ์ ์ผ ๊ฒฝ์ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
fun copyFromTo(from: Array<out Car>, to: Array<in Car>){
for (i in from.indices){
to[i] = from[i]
}
from[0] = K3() as Nothing
var any: Any = to[0] as Any
}
์ ์ฝ๋์ ๊ฐ์ด ๊ฐ์ ๋ก ์บ์คํ ํด์ฃผ๋ฉด ๋ฌธ์ ๋ ์์ต๋๋ค.
๊ฒฐ๊ตญ ํ์ ์ ์์ ์ฑ์ ๋ณด์ฅํด์ฃผ๊ธฐ ์ํด ์ ๋ค๋ฆญ์ ์ฌ์ฉํ๊ฒ ๋๋๋ฐ out, in ์ ์ด์ฉํ์ฌ ์ ๋ค๋ฆญ์ด ๊ฐ๋ ํ์ ์ ๋ํ ์ ์ฐ์ฑ์ ์กฐ๊ธ์ด๋๋ง ๋๋ ค์ค ์ ์์ต๋๋ค.
in,out ์ฌ์ฉ ์ด์ ⇒ ์ ๋ค๋ฆญ์ ํตํด ํ์ ์ ์์ ์ฑ ์ ํ์ ์กฐ๊ธ ๋์จํ๊ฒ ํ๋ฉด์ ์ฝ๋์ ์ ์ฐ์ฑ์ ์ฌ๋ ค์ฃผ๊ธฐ ์ํด!!