본문 바로가기

iOS/Swift

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 HStackStack {          // error! Type 'HStack' does not conform to protocol 'Stack'
   typealias value = Double
}
 

 

 

위처럼 value 자체가 BinaryInteger를 무조건 채택하는 타입만 선언이 가능하기 때문에

BinatyInteger 프로토콜을 따르지 않는 associatedtype은(Double) 사용 할 수 없음!

 

근데,

where 구문을 통해 확장에 제한을 둔 경우라면,

 

 

struct HStackStack {         
   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) {}
}
 

 

 

이렇게!

프로토콜에서 단일 메서드에서만 제네릭 타입을 사용해야 할 경우엔

위처럼 제네릭 메서드를 사용하는 것도 나쁘지 않다고..?........ 봅니당

 

 

 

 

 

 

 

 

.

.

.

 

음.. 프로토콜에 대해 더 할말이 있는데 

이정도에서 끝내구! 나중에 추가할 일 있으면 더 추가하겠습니당 :)

같이 프로토콜 포스팅을 달리신 분이라면 고생하셨습니다!!

만약 잘못된 내용이나 오타 및 피드백은 댓글 주세용!!

 

그럼 마지막으로 ..

넘나 .. 기여운 내블로그 화이팅.. ㅎ 

 

 

 



Calendar
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
최근 댓글
Visits
Today
Yesterday