Variance

๋“ค์–ด๊ฐ€๋ฉฐ

  • ์ œ๋„ค๋ฆญ์„ ๋‹ค๋ฃจ๊ฒŒ ๋˜๋ฉด ๋งค๋ฒˆ๋ด๋„ ์ดํ•ด๊ฐ€ ์ž˜ ์•ˆ๋˜๋Š” ๋‹จ์–ด๋“ค์ด ๋งค๋ฒˆ ๋“ฑ์žฅํ•œ๋‹ค.
    • ๋ณ€์„ฑ, ๊ณต๋ณ€, ๋ฐ˜๊ณต๋ณ€, ๊ทธ๋ฆฌ๊ณ  ๋ฌด๊ณต๋ณ€
  • ์—ญ์‹œ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค :)

๊ฐ€๋ณ€์„ฑ(Variance)์ด๋ž€?

Variance refers to how subtyping between more complex types relates to subtyping between their components.

  • Google Translate
    • Variance๋Š” ๋” ๋ณต์žกํ•œ ์œ ํ˜• ๊ฐ„์˜ ํ•˜์œ„ ์œ ํ˜•์ด ํ•ด๋‹น ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ํ•˜์œ„ ์œ ํ˜•๊ณผ ๊ด€๋ จ๋˜๋Š” ๋ฐฉ์‹์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • ์—ญ์‹œ ์ดํ•ด๊ฐ€ ์•ˆ๋˜๋‹ˆ ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์–ด์ธ subtype์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

Subtyping์ด๋ž€?

a subtype is a datatype that is related to another datatype (the supertype) by some notion of substitutability

  • A๋ผ๋Š” Data type์ด B๋ผ๋Š” Data type์„ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์„ ๊ฒฝ์šฐ

    • ์ด๋•Œ A๋Š” B์˜ Subtype์ด๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋‹ค.
    • B๋Š” A์˜ Supertype์ด๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์—ญํ• ์„ ๋Œ€์ฒด๊ฐ€ ๊ฐ€๋Šฅํ•œ์ง€๊ฐ€ Subtype์˜ ์ค‘์š”ํ•œ ํฌ์ธํŠธ์ธ๊ฑฐ ๊ฐ™๋‹ค.
    • Liskov substitution principle
    • Category Theory
  • ๊ฐ„๋‹จํ•œ ์˜ˆ๋ฅผ ๋“ค์–ด๋ณด์ž.

  • bird๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•˜๊ณ  ํ•˜์œ„์— duck, cuckoo, ostrich๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•œ๋‹ค.

  • duck, cuckoo, ostrich๋Š” bird๋ผ๋Š” ๊ณ ์œ ์˜ ํŠน์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ ๊ฐ์ž์˜ ํŠน์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

  • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— bird์™€ duck, cuckoo, ostrich๋Š” supertype - subtype์˜ ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

    • ์ด ๊ด€๊ณ„๋Š” duck, cuckoo, ostrich <: bird ๋กœ ํ‘œ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์—ฌ๊ธฐ๊นŒ์ง€๋Š” ์ดํ•ด๊ฐ€ ์ž˜ ๋œ๋‹ค.
  • ์ด์ œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ดํ•ดํ•ด๋ณด์ž.

    • ์•„๋ž˜์˜ ๊ทธ๋ฆผ์€ Java์˜ Collection Subtyping ๊ด€๊ณ„๋„๋ฅผ ํ‘œํ˜„ํ•œ ๊ฒƒ์ด๋‹ค.

  • Cat <: Animal์˜ ๊ด€๊ณ„์ผ๋•Œ
    • ๊ทธ๋ฆผ์„ ๋ณด๋ฉด List<Cat> <: List<Animal>์ด ์„ฑ๋ฆฝํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์™œ ์ž์—ฐ์Šค๋Ÿฝ์ง€ ๋ชปํ•˜์—ฌ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒƒ์ผ๊นŒ?

  • ์˜ˆ๋ฅผ ๋“ค์–ด Animal์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€์˜ Subtype์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž

    • Dog, Cat, Bird์™€ ๊ฐ™์€ Subtype์ด ์žˆ๋‹ค.
  • ์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ์•„๋ฌด ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค.

    • Animal์˜ Subtype์ธ Dog, Cat, Bird๋Š” ๋Œ€์ฒด ๊ฐ€๋Šฅํ•˜๋‹ค.
List<Animal> animals = new ArrayList<>();
animals.add(dog); // dog
animals.add(cat); // cat
animals.add(bird); // bird

์กฐ๊ธˆ ๋” ํ™•์žฅํ•ด์„œ List<Cat>๋Š” List<Animal>์˜ Subtype์ธ๊ฐ€?

  • ์ฆ‰ ๋Œ€์ฒด๊ฐ€๋Šฅํ•œ๊ฐ€?๋ผ๋Š” ๊ด€์ ์—์„œ ๋ฐ”๋ผ๋ณด์ž

  • ์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

    • ์™œ ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ• ๊นŒ?
List<Cat> cats = new ArrayList<>();
cats.add(smallCat);
cats.add(bigCat);
 
List<Animal> animals = cats // compile error
  • List<Cat>์€ ๋ฐฐ์—ด์„ Heap ๋ฉ”๋ชจ๋ฆฌ์— ์ƒ์„ฑํ•˜๋ฉฐ ์ฃผ์†Œ๋ฅผ ํ• ๋‹น๋ฐ›๋Š”๋‹ค.
    • List<Animal> = List<Cat>์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด?
    • ๋‘ ๊ฐœ์˜ List๋Š” ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ง€๊ฒŒ๋œ๋‹ค.
    • ์ด๋•Œ List<Animal>์— Dog๋ฅผ ๋„ฃ๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?
      • Dog๋Š” Animal์˜ Subtype์ด๊ธฐ ๋•Œ๋ฌธ์— Dog๋Š” List<Animal>์— ์ถ”๊ฐ€๊ฐ€ ๋œ๋‹ค.
      • ๊ฐ™์€ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋˜ List<Cat>๋Š” ์—‰๋šฑํ•œ Dog๊ฐ€ ๋“ค์–ด์™€ Type์ด ๊นจ์ง€๊ฒŒ ๋˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•œ๋‹ค.
      • ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ์œ„ํ•ด Java์—์„œ๋Š” ๊ณต๋ณ€์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
      • ๋ฐ˜๋Œ€ ์ƒํ™ฉ(List<Animal> <: List<Cat>)๋„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
      • Reference

ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ์ƒํ™ฉ์€?

  • List<Animal>์ด ๋‹จ์ˆœํžˆ ์ฝ๊ธฐ๋งŒ ํ•œ๋‹ค๋ฉด?
    • ์ฆ‰ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด ํƒ€์ž… ์•ˆ์ •์„ฑ์ด ๊นจ์งˆ ์ด์œ ๊ฐ€ ์—†์ง€ ์•Š์„๊นŒ?
    • ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ๋” ํŽธํ•˜์ง€ ์•Š์„๊นŒ?
    • Java์˜ Wildcard๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ฐ€๋ณ€์„ฑ(Variance) ์ข…๋ฅ˜์— ๋Œ€ํ•ด

  • ๊ณต๋ณ€(Covariant)
    • Subtype์€ ํ—ˆ์šฉํ•˜์ง€๋งŒ SuperType์€ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ
  • ๋ฐ˜๊ณต๋ณ€(Contravariant)
    • SuperType์€ ํ—ˆ์šฉํ•˜์ง€๋งŒ Subtype์€ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ
  • Bivariant
    • SuperType, Subtype ๋‘˜ ๋‹ค ํ—ˆ์šฉํ•˜๋Š” ๊ฒฝ์šฐ
  • ๋ฌด๊ณต๋ณ€(Invariant)
    • SuperType, Subtype ๋‘˜ ๋‹ค ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ

Reference