Swift) Protocol 이해하기 (6/6) - Protocol에 선언된 메서드는 기본값을 가질 수 없나요?
안녕하세요! 소들입니다 🥹
저... 저... 블로그 새단장 했어요!!!!!! 너무 귀엽지 않아요???ㅠㅠ
진짜 ㅠㅠㅠㅠ세상에.. ㅁ내 블로그가 세젤귀야....ㅠㅠㅠ
근데 이번 포스팅에선요
되게 간단하지만, 알아두면 좋고
또 생각할 거리도 있는 주제에 대해 다루려고 합니다!
바로 Protocol에 선언된 메서드의 파라미터는 기본 값을 가질 수 있는가! 없는가!
'에 대한 것입니다!
또한 associatedtype이 포함 되었을 떄의 경우도 볼 거예요!
생각보다 모르고계시는 분들이 많답니다... :)
그럼 공부하러 고고싱!!!
모든 포스팅은 편의 말투로 합니다~!!
1. Protocol에 선언된 메서드는 기본값을 가질 수 없습니다
정답을 ㅂㅏ로 써버리기
다음과 같이 프로토콜에 선언된 메서드에 기본값을 주려고 하면,
protocol SodeulRepository {
func fetchData(url: String = "www.sodeul.com") // error! Default argument not permitted in a protocol method
}
|
위처럼
Dafault argument not permitted
(기본 값 허용하지 않셈)
라는 에러가 뜸!!
ㄴㅔ.. 맞습니다..
프로토콜에 선언하는 메서드는 기본적으로 기본값을 가질 수 없음
그럼 기본 값을 못.. 쓰나..?
아....뉘 ..? 우리에겐..
extension
이 있잖아....! 허걱!
2. 기본값을 가지고 싶을 경우, extension을 통해 기본 메서드를 구현해주면 됩니당
protocol SodeulRepository {
func fetchData(url: String)
}
extension SodeulRepository {
func fetchData(url: String = "www.sodeul.com") {
print("sodeul blog dog cute")
}
}
|
이렇게 선언부는 그냥 그대로 냅두고,
extension을 통해서 파라미터의 기본값을 지니게 할 수 있음!!
그럼 이렇게 실제 사용할 때
프로토콜에 기본값을 가진 메서드처럼 사용할 수 있음!!!
3. 프로토콜이 associatedtype을 가지고, 파라미터 타입이 이 제네릭 타입일 경우엔 기본값을 가질 수 없습니당
이게 살짝 생각해볼 만한 포인트인데,
우리가 전 포스팅에서 배운 Protocol에서 제네릭을 사용하기 위해 다음과 같이
protocol Stack {
associatedtype value
func push(value: value)
}
|
이렇게 위처럼 associatedtype을 선언해 줬음!!
근데 어라라 나 제네릭 파라미터인 value에 기본값 주고싶은데!!!! 해서
extension을 통해 제네릭 파라미터인 value에 기본 값을 줘버리면
extension Stack {
func push(value: value = 1) { // Generic parameter 'Self' could not be inferred
...
}
}
|
이렇게
Generic parameter 'Self' could not be inferred
(제네릭 파라미터 'Self가 유추가 안 되셈)
하고 에러가 뜸!!
음.. 어찌보면 당연한 것??이라고 생각함
제네릭을 사용하는 이유가 뭐임??
바로 타입에 대한 제한을 주지 않기 위해서잖음!?!? 말 그대로 "범용 타입"!
근데 위처럼 extension을 통해 제네릭 파라미터인 value의 타입을
1 즉, Int로 제한시켜 버리면,,
이건 뭐... value란 associatedtype을 Int로 사용할 녀석들만..
저 메서드 확장이 가능한 건가..?
싶잖음??
안도 ㅣ면 가능하게 하라...
assosicatedtype 파라미터에 기본값을 주기 위해선
associatedtype 타입이 기본값으로 1이란 값을 가질 수 있게
associatedtype 타입 자체에 BinaryInteger 프로토콜을 채택하고 있어야 한다는
제약을 다음과 같이 주거나,
protocol Stack {
associatedtype value: BinaryInteger
func push(value: value)
}
extension Stack {
func push(value: value = 1) {
...
}
}
|
또는
value라는 associatedtype이 BInaryInteger를 채택하고 있을 경우만
extension이 가능하게 제한을 두어도 됨
extension Stack where value: BinaryInteger {
func push(value: value = 1) {
...
}
}
|
위처럼!!
위 두 가지 방식을 사용했을 경우,
더이상 기본값을 1로 가지는 push 메서드에 에러는 나지 않음!!
위 두 방법의 차이점이라고 하면,
associatedtype 자체에 BinaryInteger를 채택하고 있어야 한다는 제약을 줄 경우,
struct HStack: Stack { // error! Type 'HStack' does not conform to protocol 'Stack'
typealias value = Double
}
|
위처럼 value 자체가 BinaryInteger를 무조건 채택하는 타입만 선언이 가능하기 때문에
BinatyInteger 프로토콜을 따르지 않는 associatedtype은(Double) 사용 할 수 없음!
근데,
where 구문을 통해 확장에 제한을 둔 경우라면,
struct HStack: Stack {
typealias value = Double
func push(value: value) {
...
}
}
|
확장에만 제한이 걸리는 것이기 때문에,
associatedtype 자체엔 제약이 없지만 BinaryInteger를 채택하지 않은 Double의 경우,
extension에 구현된 기본 메서드를 제공받을 수 없어
이땐 해당 메서드를 직접 구현해줘야 함!(그러면 사용 가능!)
움.. 근데 associatedtype 자체에 제한을 두는 것보다
where을 통해 조건부 확장을 하는 게 좀 더 낫나..?
모르겠다 ㅎ
+ 또 다른 방법으론 이전 포스팅에서 배웠듯,
제네릭 메서드를 사용하셔도 됨니당
protocol Stack {
func push<T: Equatable>(value: T)
}
extension Stack {
func push<T: Equatable>(value: T = 1) {}
}
|
이렇게!
프로토콜에서 단일 메서드에서만 제네릭 타입을 사용해야 할 경우엔
위처럼 제네릭 메서드를 사용하는 것도 나쁘지 않다고..?........ 봅니당
.
.
.
음.. 프로토콜에 대해 더 할말이 있는데
이정도에서 끝내구! 나중에 추가할 일 있으면 더 추가하겠습니당 :)
같이 프로토콜 포스팅을 달리신 분이라면 고생하셨습니다!!
만약 잘못된 내용이나 오타 및 피드백은 댓글 주세용!!
그럼 마지막으로 ..
넘나 .. 기여운 내블로그 화이팅.. ㅎ