04 August 2017

Swift로 코드를 작성하다보면 Protocol Extension에 구현된 메소드 또는 계산 속성과 클래스 또는 구조체에 구현된 메소드와 계산 속성 이름이 같으면 어떻게 동작하지 라는 고민을 하게 됩니다.

A라는 프로토콜에 foo라는 함수를 명시한 뒤, Extension에 foo 함수를 구현합니다.

protocol A {
	func foo() -> String
}

extension A {
	func foo() -> String {
		return "foo"
	}
}

class B: A {}

클래스 B는 프로토콜 A를 따르기 때문에, 프로토콜 A의 foo 함수를 B에서 사용할 수 있습니다.

print(B().foo()) // foo

그러면 클래스 B에다 foo 함수를 작성하면 어떻게 될까요?

class B: A {
	func foo() -> String {
		return "Foo"
	}
}

let b: A = B()
print(b.foo()) // Foo

컴파일 에러가 발생하지 않으며, B에서 작성된 foo 함수의 결과값이 반환됩니다. 클래스 B의 foo 함수를 찾아서 호출되기 때문입니다.

그렇다면 프로토콜 A에 정의되지 않은 함수를 Extension에 구현하고, 클래스 B에 extension에 구현된 함수의 이름과 같게 구현하면 어떻게 될까요?

protocol A {
	func foo() -> String
}

extension A {
	func foo() -> String {
		return "foo"
	}
	func bar() -> String {
		return "bar"
	}
}

class B: A {
	func foo() -> String {
		return "Foo"
	}
	func bar() -> String {
		return "Bar"
	}
}

이제 클래스 B의 bar 함수를 호출해봅시다.

let b: A = B()
print(b.bar()) // bar

앞에서 foo 함수 호출과는 다르게 bar 함수 호출시 bar로 출력이 되었습니다. 그러면 변수 b의 타입을 클래스 B로 변경하여 다시 호출봅시다.

let b: B = B()
print(b.bar()) // Bar

변수 b의 타입이 달리지니 결과도 달라졌습니다. 클래스 또는 구조체 타입이냐 프로토콜 타입이냐에 따라 프로토콜에 정의되지 않은 함수를 호출시 결과가 달라집니다.

다음 포스팅에서 왜 출력값이 달라지는지 알아보도록 하겠습니다.


다음 포스팅 참고 자료