Programing Langauge/swift

protocol 학습하기 (2) [ generic, 합성, 채택 체크 ]

Hamp 2024. 8. 25. 15:19
반응형

 

프로토콜에 제네릭 및 제약조건 적용하기

제네릭 (범용 타입)은 런타임 시 타입을 결정하게하여 함수 또는 변수에 상황에 맞는 타입을
사용할 수 있게하는 기능이다.
제네릭 역시 프로토콜에 적용 할 수 있으며, 프로토콜 타입을  재네릭으로 사용할 수 있다.

 

1) 프로토콜에 제네릭 사용하기 

기본 제네릭 패턴 또는 where과 조합해서 쓸 수 있다.

protocol SomeProtocol {
    
    func f1<T: Equatable>(param: T) // 단순 제네릭 이용
    

    func f2<T>(param: T) where T: Equatable // 제네릭 + where 이용
    
}

 

2) 제네릭에 프로토콜 타입으로 사용하기

프로토콜 역시 제네릭 타입으로 사용할 수 있다.

protocol SomeProtocol {
    
    func someFunc() -> Void
}

class SomeClass: SomeProtocol {
    func someFunc() {}
}

func genericFunc<T: SomeProtocol>(generic: T) -> Void {
    generic.someFunc()
}

func genericFunc2<T>(generic: T) -> Void where T: SomeProtocol {
    generic.someFunc()
}

 


프로토콜 합성 

여러가지 프로토콜을 모두 만족해야할 때 & 연산자를  사용해서 표시한다.

가장 대표적인 프로토콜로는 Codable  프로토콜이 생각난다.

 

Codable = Decodable + Encodable 인 형태이다. 한번 진짜 그런지 확인해보자.

아래에서 보다시피 Codable은 새로운 프로토콜이 아닌 단순 Decodable 과 Encodable이 합성된 typealias이다.

Codable

프로토콜 선언 시 다음과 같이 사용할 수 도 있다.

 

protocol SomeProtocol {
    
    func someFunc() -> Void
}

protocol SomeProtocol2 {
    func someFunc2() -> Void
}

protocol SomeProtocol3:  SomeProtocol & SomeProtocol2 {
    func someFunc3() -> Void
}


class SomeClass: SomeProtocol3 {
    
    func someFunc() {}
    
    func someFunc2() {}
    
    func someFunc3() {}
    
}

프로토콜 채택 체크 

프로토콜은 체크 여부는 is, as , where을 통해 할 수 있다.

 

1) is 

프로토콜을 준수하면 true 아니면 false 

protocol SomeProtocol {
    
    func someFunc() -> Void
}

class SomeClass: SomeProtocol {
    func someFunc() {}
}

var someC = SomeClass()

if someC is SomeProtocol {
    print("Some Class confirmed SomeProtocol") // ✅
} else {
    print("Some Class doesn't confirmed SomeProtocol ") ❌
}

2) as

as는 구현체의 타입을 프로토콜 타입으로 변환한다.

as? 는 채택하지 않았을 경우 nil을 리턴 as!는 런타임 에러를 발생시킵니다.

 

guard let p = someC as? SomeProtocol else {
    fatalError()
}

let pp = someC as! SomeProtocol

 

3) where

where은 크게 2가지 역할을 한다.

첫번 째는 특정 패턴과 조합하여 조건을 추가할 수 있고 두번 째는  재네릭 타입에 대한 제약을 추가할 수 있다.

우리는 프로토콜에 대한 사용을 배우고 있으므로 두번 째 역할을 이용한다.

 

func genericFunc2<T>(generic: T) -> Void where T: SomeProtocol {
    generic.someFunc()
}
반응형