[Swift] final ν‚€μ›Œλ“œ

parkgyurimΒ·2022λ…„ 7μ›” 18일
0

Swift

λͺ©λ‘ 보기
5/8
post-thumbnail

class 의 μ„ μ–Έ μ•žμ— final μ΄λΌλŠ” ν‚€μ›Œλ“œλ₯Ό λ³Έ 적 μžˆμœΌμ‹ κ°€μš”?

μš°μ„  final ν‚€μ›Œλ“œλ₯Ό μ•Œμ•„λ³΄κΈ° 전에, Swiftμ—μ„œ νŠΉμ • ν•¨μˆ˜ λ˜λŠ” λ³€μˆ˜λ₯Ό λΆˆλŸ¬μ˜€λŠ” λ§€μ»€λ‹ˆμ¦˜μΈ Dispatch μ—λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

πŸ’‰ Dispatch

Swiftμ—μ„œ Dispatch 방법은 Type 에따라 2κ°€μ§€λ‘œ λ‚˜λ‰˜κ²Œ λ©λ‹ˆλ‹€. (Swift의 Type μ•Œμ•„λ³΄κΈ°)

Static Dispatch

Static Dispatch λŠ” Direct Call 이라고도 뢈리며, 컴파일 νƒ€μž„μ— 호좜될 ν•¨μˆ˜ λ˜λŠ” λ³€μˆ˜λ₯Ό κ²°μ • ν•˜μ—¬ λŸ°νƒ€μž„λ•Œ κ·ΈλŒ€λ‘œ μ‹€ν–‰ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 컴파일 νƒ€μž„μ— 결정이 λ˜λ―€λ‘œ λŸ°νƒ€μž„μ—μ„œ μ„±λŠ₯상 이점이 μžˆμŠ΅λ‹ˆλ‹€. Value Type인 struct, enum λ“±λ“± 은 Static Dispatch λ₯Ό ν•˜κ²Œ λ©λ‹ˆλ‹€. (λ‹Ήμ—°νžˆ 상속이 λΆˆκ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ—..!)

Dynamic Dispatch

Dynamic Dispatch λŠ” Indirect Call 이라고도 뢈리며, λŸ°νƒ€μž„μ— 호좜될 ν•¨μˆ˜ λ˜λŠ” λ³€μˆ˜λ₯Ό κ²°μ • ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. ν•¨μˆ˜ 포인터 배열인 vTable(Virtual Dispatch Table) μ΄λΌλŠ” 것을 μœ μ§€ν•˜λ©° ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ ν˜ΈμΆœν• λ•Œ, vTable 을 μ°Έμ‘°ν•˜μ—¬ 싀행될 λŒ€μƒλ₯Ό κ²°μ •ν•©λ‹ˆλ‹€. (슈퍼 ν΄λž˜μŠ€μ— μžˆλŠ” λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν• μ§€, μ„œλΈŒ ν΄λž˜μŠ€μ— μžˆλŠ” λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν• μ§€!)
Reference Type 은 μƒμ†μ˜ κ°€λŠ₯성이 있기 λ•Œλ¬Έμ— Reference Type 인 class, actor λ“±λ“±μ—μ„œλŠ” 기본적으둜 Dynamic Dispatch λ₯Ό ν•˜κ²Œ λ©λ‹ˆλ‹€.

πŸ“Œ protocol κ³Ό extension

  • protocol μ—μ„œ μ„ μ–Έλœ λ©”μ„œλ“œλ₯Ό extension 을 톡해 λ””ν΄νŠΈ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•œ 경우
    protocol 을 conform ν•œ ν΄λž˜μŠ€μ—μ„œ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„μ„ ν–ˆμ„ μˆ˜λ„ 있고 μ•ˆ ν–ˆμ„ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 이런 경우 Dynamic Dispatch λ₯Ό ν•˜κ²Œ λ©λ‹ˆλ‹€.

  • protocol μ—μ„œ μ„ μ–Έλ˜μ§€ μ•Šκ³ , extension 을 톡해 κ΅¬ν˜„ν•œ 경우
    protocol 을 conform ν•œ ν΄λž˜μŠ€μ—μ„œ ν•΄λ‹Ή λ©”μ„œλ“œ κ΅¬ν˜„μ΄ ν•„μš”μ—†κΈ° λ•Œλ¬Έμ—, ν•΄λ‹Ή ν΄λž˜μŠ€μ—μ„œ λ©”μ„œλ“œ ν˜ΈμΆœμ‹œ extension 에 κ΅¬ν˜„ν•œ λ©”μ„œλ“œλ₯Ό Static Dispatch ν•˜κ²Œ λ©λ‹ˆλ‹€.

Dispatch 방식을 ν†΅ν•œ μ„±λŠ₯ ν–₯μƒμ˜ 이유둜,
Swiftμ—μ„œ protocol extension 을 ν†΅ν•œ POP λ₯Ό 지ν–₯ν•˜λŠ” ν•˜λ‚˜μ˜ 이유라고 생각이 λ©λ‹ˆλ‹€!

Avoid Dynamic Dispatch

Advice: Use 'final' when you know the declaration does not need to be overridden - πŸ“š Github apple/swift/OptimizationTips

Dynamic Dispatch 의 λͺ¨λ“  과정이 λŸ°νƒ€μž„μ— μΌμ–΄λ‚˜κΈ° λ•Œλ¬Έμ— μ˜€λ²„ν—€λ“œκ°€ λ°œμƒν•˜κ³ , μ„±λŠ₯상 손해 λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μ• ν”Œμ—μ„œλŠ” νŠΉμ • class, method, property κ°€ μƒμ†λ˜κ±°λ‚˜ μž¬μ •μ˜λ  κ°€λŠ₯성이 μ—†λ‹€λ©΄, ꡳ이 Dynamic Dispatch λ₯Ό ν•˜μ§€ μ•Šκ³  Static Dispatch λ₯Ό ν•  수 μžˆλŠ” 방법을 제곡 ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.


πŸ›  final keyword

final ν‚€μ›Œλ“œλŠ” ν•΄λ‹Ή class, method, property κ°€ 상속이 λΆˆκ°€λŠ₯ν•˜κ³  ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ μ˜€λ²„λΌμ΄λ”©ν•  수 μ—†λ‹€λŠ” 것을 λͺ…μ‹œν•˜λŠ” ν‚€μ›Œλ“œ μž…λ‹ˆλ‹€.

μ‚¬μš© 방법은 κ°„λ‹¨ν•©λ‹ˆλ‹€!

class

class κ°€ 상속이 λΆˆκ°€λŠ₯ν•˜λ‹€λŠ” 것을 λͺ…μ‹œν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

final class exampleClass {
	var 
}

class derivedExampleClass : exampleClass { // πŸ”₯ ERROR
	...
}

β†’ final ν‚€μ›Œλ“œκ°€ 뢙은 ν΄λž˜μŠ€λŠ” λ‹€λ₯Έ ν΄λž˜μŠ€μ—μ„œ 상속을 받을 수 μ—†μŠ΅λ‹ˆλ‹€!

method, property

method, property κ°€ μ„œλΈŒ ν΄λž˜μŠ€μ—μ„œ μž¬μ •μ˜ (μ˜€λ²„λΌμ΄λ”©) 이 될 수 μ—†λ‹€λŠ” 것을 λͺ…μ‹œν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

class exampleClass {
	final var exampleVar : [Int] = ... 
    final func exampleMethod() { ... }
}

class derivedExampleClass : exampleClass {
	override var exampleVar : [Int] = ... // πŸ”₯ ERROR
    override func exampleMethod() { ... } // πŸ”₯ ERROR
}

β†’ final ν‚€μ›Œλ“œκ°€ 뢙은 method λ‚˜ property λŠ” μ„œλΈŒ ν΄λž˜μŠ€μ—μ„œ μž¬μ •μ˜ (μ˜€λ²„λΌμ΄λ”©) ν•  수 μ—†μŠ΅λ‹ˆλ‹€!

κ²°κ³Ό

결과적으둜 final ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν–ˆμ„λ•Œ, ν•΄λ‹Ή class, method, property λ₯Ό μ‚¬μš©ν•  λ•ŒλŠ” 더 이상 Dynamic Dispatch κ°€ μ•„λ‹Œ Static Dispatch λ₯Ό 톡해 Directly Call 을 ν•˜κΈ° λ•Œλ¬Έμ— λŸ°νƒ€μž„ μ„±λŠ₯ ν–₯상을 κΈ°λŒ€ν•  수 μžˆμŠ΅λ‹ˆλ‹€!


πŸ‘ 마무리

μ˜€λŠ˜μ€ Swift의 Type 에 λ”°λ₯Έ Dispatch 방식과 final ν‚€μ›Œλ“œμ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

참고둜 μ €λŠ” class λ₯Ό μƒμ„±ν• λ•ŒλŠ” 항상 final ν‚€μ›Œλ“œλ₯Ό 뢙이고, κ°„ν˜Ή 상속이 ν•„μš”ν•œ κ²½μš°μ—λ§Œ final ν‚€μ›Œλ“œλ₯Ό μ‚­μ œν•˜λŠ” μŠ΅κ΄€μ„ κ°–κ³  μžˆμŠ΅λ‹ˆλ‹€!

Swift 의 μž‘λ™ 방식을 κ³΅λΆ€ν•΄λ‚˜κ°€λ©΄μ„œ, κΈ°λ³Έ μžλ£Œν˜•λ“€μ΄ struct 둜 κ΅¬ν˜„λ˜μ–΄μžˆλŠ” 이유, Optional 이 Enum 으둜 κ΅¬ν˜„λ˜μ–΄μžˆλŠ” 이유 등을 μ‘°κΈˆμ”© 이해가 λ˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

λ˜ν•œ 기쑴의 class μ€‘μ‹¬μ˜ OOP 의 Dynamic Dispatch λΌλŠ” 약점을 λ³΄μ™„ν•˜κΈ° μœ„ν•˜μ—¬, protocol 의 extension 을 μ‚¬μš©ν•œ 상속과 닀쀑 상속과 같은 효과λ₯Ό 얻을 수 있음과 λ™μ‹œμ— Static Dispatch λ₯Ό ν™œμš©ν•  수 μžˆλ„λ‘ POP λ₯Ό 지ν–₯ν•˜λŠ” μ• ν”Œμ΄ ꡉμž₯히 λ˜‘λ˜‘ν•˜κ³  ν₯미둭게 λŠκ»΄μ‘ŒμŠ΅λ‹ˆλ‹€!

ν‹€λ¦° 정보 λ˜λŠ” κΆκΈˆν•œ 점이 μžˆλ‹€λ©΄ λŒ“κΈ€ λΆ€νƒλ“œλ¦½λ‹ˆλ‹€! μ½μ–΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€β€ΌοΈ

0개의 λŒ“κΈ€