[Swift] Method Dispatch (2): ๋ ๋ณต์กํ ์ํฉ์ Method Dispatch
์ผ๋จ ์ ๋ฆฌ.. Static Dispatch, Dynamic Dispatch
์ง๋ ํฌ์คํธ์์ Static Dispatch์ Dynamic Dispatch๋ฅผ ์ ๋ฆฌํด๋ณด์๋๋ฐ์, Static Dispatch๋ ์ธ์คํด์ค์์ ๋ฉ์๋๊ฐ ํธ์ถ๋ ๋ ์ค์ ๋ก ์ด๋ค ๋ฉ์๋๊ฐ ํธ์ถ๋ ์ง ์ปดํ์ผ ํ์์ ๊ฒฐ์ ํ ์ ์๋ ๊ฒฝ์ฐ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ Dynamic Dispatch๋ ๋ฐํ์์ vtable์ด๋ผ๋ ํ ์ด๋ธ์ ์ค์ ์คํํ ๋ฉ์๋์ ์ฃผ์๋ฅผ ์ฐพ์ ๊ฒฐ์ ํ๋ ๊ฒฝ์ฐ์์ต๋๋ค.
๋ฐํ์์ ํ ์ด๋ธ์ ๋ฃฉ์ ํด์ผํ๋ ์ค๋ฒํค๋ ๋๋ฌธ์ Dynamic Dispatch๋ ์ฑ๋ฅ์๋ ๋ถ์ ์ ์ธ ์ํฅ์ ์ค๋ค๋ ๊ฒ๋ ์ง์ด๋ดค์์ฃ . ํ์ง๋ง ์์๊ณผ ๋คํ์ฑ์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ Dynamic Dispatch์ ์ฌ์ฉ์ด ํ์์ ์ด์์ต๋๋ค.
๊ฒฐ๊ตญ ์ง๋ ํฌ์คํธ์์๋ ๊ตฌ์กฐ์ฒด, ์ด๊ฑฐํ ๋ฑ, ๊ฐ ํ์ ์ธ์คํด์ค๋ค์ Static Dispatch, ์ฐธ์กฐ ํ์ ์ธ์คํด์ค์ธ ํด๋์ค๋ Dynamic Dispatch๋ก ๊ฒฐ๋ก ์ด ๋ฌ์๋๋ฐ์, ์ข ๋ ๋ณต์กํ ์ํฉ์ ๊ณ ๋ฏผํด๋ด ์๋ค.
์๋ฌธ์ 1: ํ๋กํ ์ฝ์ ์ฑํํ๋ ๊ตฌ์กฐ์ฒด๋ ์ด์ฉ๊ฑด๋ฐ?
์ค์ํํธ์ ์ง์ ์ ์ธ ์์์ ํด๋์ค๋ง์ด ๊ฐ๋ฅํ์ง๋ง, ๊ตฌ์กฐ์ฒด๋ก๋ ์์์ ๊ฐ๋ ์ ์ ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์์ต๋๋ค. ๋ฐ๋ก ํ๋กํ ์ฝ์ ์ฌ์ฉ์ด์ฃ .
class Test {
func printTest() {
print("test")
}
}
class TestA: Test {
override func printTest() {
print("testA")
}
}
class TestB: Test {
override func printTest() {
print("testB")
}
}
let tests = [Test(), TestA(), TestB()]
for test in tests {
print(type(of: test))
test.printTest()
}
์ง๋ ํฌ์คํธ์์ ์ฌ์ฉํ๋ ์ด ํด๋์ค๋ค์ ๊ตฌ์กฐ์ฒด์ ํ๋กํ ์ฝ๋ก ๋ฐ๊ฟ๋ณผ๊ฒ์!
protocol TestPrintable {
func printTest()
}
struct Test: TestPrintable {
func printTest() {
print("test")
}
}
struct TestA: TestPrintable {
func printTest() {
print("testA")
}
}
struct TestB: TestPrintable {
func printTest() {
print("testB")
}
}
let tests: [TestPrintable] = [Test(), TestA(), TestB()]
for test in tests {
test.printTest()
}
์ด๋ ๊ฒ ํ๋ฉด ๋์ผํ ์ถ๋ ฅ์ด ๋์ค๊ฒ ์ฃ ? ์ด์ tests ๋ฐฐ์ด์ ์์ ํ์ ์ ํ๋กํ ์ฝ์ ํ์ ์ธ TestPrintable์ด ๋๊ฒ ๋ค์.
์, ๊ทธ๋ผ ๋ค์ ์๋ฌธ์ ์ด ์๊น๋๋ค. ํ๋กํ ์ฝ๋ง ๋ณด๊ณ ์ค์ ๊ตฌํ์ฒด๊ฐ ๋ญ์ง ์ด๋ป๊ฒ ์์..?
์ปดํ์ผ ํ์์๋ TestPrintable์ ์ ์ธ๋ง ์๊ณ ์๊ณ , ์ ์๋ฅผ ์ฐพ์๊ฐ๋ ค๋ฉด ๊ฐ ์ธ์คํด์ค๊ฐ ๊ฐ์ง ๋ฉ์๋ ์ ์๋ฅผ ์ฐพ์๊ฐ์ผ๊ฒ ์ฃ ? ๊ฒฐ๊ตญ ์ด๋ฒ์๋ Dynamic Dispatch๊ฐ ๋๊ฒ ๋ค์.
ํ๋กํ ์ฝ์ ์ฑํํ ๊ตฌ์กฐ์ฒด์ Dynamic Dispatch
๊ตฌ์กฐ์ฒด๋ vtable์ ์ธ ๊ฒ ๊ฐ์ง๋ง, ๊ทธ๋ ์ง ์์ต๋๋ค. ๊ตฌ์กฐ์ฒด๋ ๊ณตํต์กฐ์์ธ ์ธ์คํด์ค๊ฐ ์์ผ๋๊น์.
๊ทธ๋์ ์ด๋ฒ์๋ ์๋ก์ด ํ ์ด๋ธ์ธ Protocol Witness Table(PWT)์ด ์ฌ์ฉ๋ฉ๋๋ค.
Protocol Witness Table์ ํ๋กํ ์ฝ์ ์ฑํํ๋ ๊ฐ ๊ตฌ์กฐ์ฒด ์ธ์คํด์ค๊ฐ ํ๋์ฉ ๊ฐ์ง๊ณ , ํน์ ํ ๋ฉ์๋์ ๋ํ ์ค์ ๊ตฌํ์ ์ด ํ ์ด๋ธ์ ์ฐ๊ฒฐ์์ผ๋ก๋๋ค.
WWDC์์ ๋ฐํํ ์๋ฃ์์๋ ์ด๋ ๊ฒ ํํํ๊ณ ์์ด์. ๋ฐฐ์ด์ ๋ด๊ธด ์ธ์คํด์ค๋ค์ด ๋ด๋ถ์ PTW๋ฅผ ๊ฐ์ง๊ณ ์ฌ๊ธฐ์ ์ค์ ๊ตฌํ์ ๋ํ ๋งํฌ๊ฐ ๋ง๋ค์ด์ ธ ์๋ ๊ฒ์ด์ฃ .
์ด๋ ๊ฒ ํ๋ฉด ๋ฐํ์์ ๋ฐฐ์ด ์์๊ฐ ๊ฐ์ง ํ ์ด๋ธ์ ํ ๋ฒ ์ฝ์ด์ ์ฝ๋๋ฅผ ์ฐพ์๊ฐ์ผํ๋ Dynamic Dispatch๊ฐ ๋๊ฒ ์ฃ !
์๋ฌธ์ 2: ํ๋กํ ์ฝ์ Extension ํด์ ๋ฉ์๋๊ฐ ์ ์๋์ด ์๋ค๋ฉด?
์ด๋ฐ ๊ฒฝ์ฐ๋ ์ด๋จ๊น์?
protocol TestPrintable {
}
extension TestPrintable {
func printTest() {
print("hello")
}
}
struct Test: TestPrintable {
func printTest() {
print("test")
}
}
struct TestA: TestPrintable {
func printTest() {
print("testA")
}
}
struct TestB: TestPrintable {
func printTest() {
print("testB")
}
}
let tests: [TestPrintable] = [Test(), TestA(), TestB()]
for test in tests {
test.printTest()
}
ํ๋กํ ์ฝ์ extensionํด์ ๊ธฐ๋ณธ ๋ฉ์๋๋ฅผ ์ ์ํด๋๊ณ ์คํ์ ํด๋ณด์์ต๋๋ค.
๊ฒฐ๊ณผ๋,
hello
hello
hello
์ด๋ ๊ฒ ๊ธฐ๋ณธ ๋ฉ์๋๊ฐ ์คํ๋ฉ๋๋ค. ์๋ํ๋ฉด ๋ฐฐ์ด์ ์์ ํ์ ์ด TestPrintable์ด๊ธฐ ๋๋ฌธ์ ์ด ํ์ ์ ๋ํ ๋ฉ์๋๊ฐ ๊ณง๋ฐ๋ก ์คํ๋๋ ๊ฒ์ด์ฃ . ๊ฐ ์ธ์คํด์ค์ ์ ์๋ printTest๋ ํ๋กํ ์ฝ๋ก๋ถํฐ ์ฑํ๋ฐ์ ๋ฉ์๋๊ฐ ์๋๋๋ค.
์ค์ ๋ก XCode์์ ์๋์์ฑ๋ ์ง์ํด์ฃผ์ง ์๋ค์ใ ใ
์๋๋ ์ด๋ ๊ฒ ํด์ค์ผํ๋๋ฐ ๋ง์ด์ฃ ..
์ฆ, ์ด๋ฐ ๊ฒฝ์ฐ๋ ์ธ์ ๋ ํ๋กํ ์ฝ์ ๊ธฐ๋ณธ ๋ฉ์๋๋ฅผ ์คํํ๋ Static Dispatch๋ก ๋์ํฉ๋๋ค.
์๋ฌธ์ 3: ํ๋กํ ์ฝ์ ์ธํฐํ์ด์ค๊ฐ ์๊ณ , ๊ธฐ๋ณธ ๋ฉ์๋๊ฐ Extension์ผ๋ก ์ ์๋ ๊ฒฝ์ฐ๋?
์์ ์์์์ ์ธํฐํ์ด์ค๋ง ์ถ๊ฐํด๋ณด๊ฒ ์ต๋๋ค.
protocol TestPrintable {
func printTest()
}
extension TestPrintable {
func printTest() {
print("hello")
}
}
struct Test: TestPrintable {
func printTest() {
print("test")
}
}
struct TestA: TestPrintable {
func printTest() {
print("testA")
}
}
struct TestB: TestPrintable {
func printTest() {
print("testB")
}
}
let tests: [TestPrintable] = [Test(), TestA(), TestB()]
for test in tests {
test.printTest()
}
์ด๋ฒ์๋ ํ๋กํ ์ฝ์ ์ธํฐํ์ด์ค๊ฐ ์กด์ฌํ๊ณ , ์ด๋ฅผ ์ฑํํ๋ ๊ตฌ์กฐ์ฒด์์ ๊ฐ๊ฐ ์์ ์ ๊ตฌํ์ฒด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์ ์ฝ๋๋ฅผ ์คํํด๋ณด๋ฉด ๊ฒฐ๊ณผ๋ ์๋์ฒ๋ผ ๋์ค๋๋ฐ์,
test
testA
testB
์ด๋ฒ์๋ ํ๋กํ ์ฝ์ ์ฑํํ ์ธ์คํด์ค๋ค์ ๋ฉ์๋๊ฐ ์คํ๋ฉ๋๋ค. ๊ฐ ๋ฉ์๋๋ค์ด ํ๋กํ ์ฝ์ ๋ฐ์ ๊ตฌ์กฐ์ฒด์์ ์ ์๋๊ณ ์๋ ์ํฉ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ๊ฒฝ์ฐ๋ ํ๋กํ ์ฝ์ ์ฑํํ ๊ตฌ์กฐ์ฒด์ ๋ฉ์๋๊ฐ ์ฐ์ ์ ์ผ๋ก ์คํ๋ฉ๋๋ค.
๋ฐ๋ผ์ ์ด๋ฐ ๊ฒฝ์ฐ๋ Dynamic Dispatch ์ ๋๋ค.
์๋ฌธ์ 4: ํด๋์ค์ Extension์?
์ด๋ฒ์ ํด๋์ค๋ฅผ Extensionํ๋ ๊ฒฝ์ฐ์ ๋๋ค.
class Test {
func printTest() {
print("test")
}
}
extension Test {
func printExtension() {
print("extension")
}
}
class TestA: Test {
override func printTest() {
print("testA")
}
override func printExtension() {
print("extensionA")
}
}
class TestB: Test {
override func printTest() {
print("testB")
}
}
let tests = [Test(), TestA(), TestB()]
for test in tests {
test.printExtension()
}
์ต์์ ํด๋์ค์ Extension์ ์๋ก์ด ๋ฉ์๋ ์ถ๊ฐํ๊ณ TestA์์ ์ค๋ฒ๋ผ์ด๋ฉ์ ํ๋ ค๊ณ ํฉ๋๋ค.
ํ์ง๋ง ์ด๋ ๊ฒ ์๋ฌ๊ฐ ๋ฉ๋๋ค.. Extension์ผ๋ก ๋ง๋ ๋ฉ์๋๋ ์ค๋ฒ๋ผ์ด๋ฉ์ด ๋ถ๊ฐ๋ฅํ๋ค๊ณ ํ๋ค์.. Objective-C ๋ฐํ์์ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฅํ๋ค๊ณ ํฉ๋๋ค.
๋ง์ฝ Objective-C ๋ฐํ์์ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด ํญ์ ์ต์์ ํด๋์ค์ ๋ฉ์๋๋ง ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก Static Dispatch ๊ฐ ๋ฉ๋๋ค.
์ ๋ฆฌ
https://www.rightpoint.com/rplabs/switch-method-dispatch-table
์ด ๊ธ์ ํ๋ก ์ ์ ๋ฆฌ๋์ด ์์ด์ ๊ทธ๋๋ก ๊ฐ์ ธ์๋ด ๋๋ค!
- 1) ๊ฐ ํ์ : ์์ํ ๊ฐ ํ์ , ํ๋กํ ์ฝ์ ์ฑํํ์ง ์๋ ๊ตฌ์กฐ์ฒด๋ enum์ ํญ์ Static Dispatch์ ๋๋ค. ์ด๋ค ๋ฉ์๋๋ฅผ ์คํํ์ง๋ ๋๋ฌด๋ ๋ช ํํ๋๊น์!
- 2) ํ๋กํ ์ฝ: ํ๋กํ ์ฝ์ ์ฑํํ๋ ํ์ ๋ค์ ๊ธฐ๋ณธ์ ์ผ๋ก Dynamic Dispatch์ ๋๋ค. ์ฌ๊ธฐ์ ์ฌ์ฉํ๋ ํ ์ด๋ธ์ Protocol Witness Table ์ด๊ตฌ์. ํ์ง๋ง Protocol์ ์ธํฐํ์ด์ค์ ํฌํจ๋์ง ์๋ ๊ธฐ๋ณธ ๋ฉ์๋๋ค์ ํญ์ ๊ธฐ๋ณธ ๋ฉ์๋๊ฐ ํธ์ถ๋๊ธฐ ๋๋ฌธ์ Static Dispatch ์ ๋๋ค.
- 3) ํด๋์ค: ํด๋์ค๋ ๋คํ์ฑ๊ณผ ์์ ๋๋ฌธ์ ๊ธฐ๋ณธ์ ์ผ๋ก Dynamic Dispatch์ด๊ณ , vtable์ ์ด์ฉํด์ ๋ฉ์๋๋ฅผ ์คํํฉ๋๋ค. ํด๋์ค์ extension์ผ๋ก ์ ์๋ ๋ฉ์๋๋ Objective-C ๋ฐํ์์ ์ฌ์ฉํ์ง ์์ผ๋ฉด ์ค๋ฒ๋ผ์ด๋ฉํ ์ ์๊ธฐ ๋๋ฌธ์ Static Dispatch ์ ๋๋ค.
Reference
- https://developer.apple.com/videos/play/wwdc2016/416/
- https://babbab2.tistory.com/144?category=828998
- https://www.rightpoint.com/rplabs/switch-method-dispatch-table
- https://zeddios.tistory.com/597
'๐ ์์ด-์ค-์์ค > ๐ค ์ค์ํํธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] Method Dispatch ๋ฐํ์๋ฃ (2) | 2021.12.28 |
---|---|
[Swift] Method Dispatch (3): Dynamic Dispatch๋ฅผ ์ค์ฌ๋ณด์ (0) | 2021.12.26 |
[Swift] Method Dispatch (1): Static Dispatch vs. Dynamic Dispatch (1) | 2021.12.26 |
[๋ฉด์ ์ง๋ฌธ] ์ค์ํํธ(Swift) 75๋ฌธ 75๋ต (2) | 2021.12.24 |
[Swift] GCD(Grand Central Dispatch) - Dispatch Queue (2) | 2021.10.25 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote