Swift의 온도

Swift #14 - 프로토콜, extension

IT의 온도 2021. 1. 22. 01:48

 

1. 프로토콜

 

- 인터페이스와 구현

#인터페이스(interface)

#구현(implementation)

#클래스 : 인터페이스 + 구현

#프로토콜 : 인터페이스 Only

 *구현이 없어서 단독 사용 불가

 *클래스, 구조체와 함께 사용

 *메소드, 프로퍼티 구현 약속

 

- 프로토콜 정의와 채택

*프로토콜 정의
 
protocol PROTOCOL_NAME {
}
 
*채택
 
class CLASS_NAME : PROTOCOL_NAME {
}
cs

 

#클래스와 프로토콜

 *상속과 프로토콜 : 부모 클래스를 첫 번째, 프로토콜은 두 번째부터

 

- 프로토콜 사용 예제

*프로토콜 정의
 
protocol Singing {
    func sing()
}
 
*클래스 채택
 
class Bird : Singing {
    func sing() {
        print("짹짹짹")
    }
}
 
*객체 생성과 사용
 
var sparrow = Bird()
sparrow.sing()
cs

 

#같은 인터페이스, 다양한 구현

*클래스, 구조체, enum에 채택
 
class Bird : Singing {
    func sing() {
        print("짹짹짹~")
    }
}
struct Cat : Singing {
    func sing() {
        print("갸르릉 갸르릉")
    }
}
cs

 

- 다중 프로토콜 채택

protocol Dancing {
    func dance()
}
class Human : Dancing, Singing {
    func sing() {
        print("랄랄라~")
    }
    func dance() {
        print("춤추기")
    }
}
 
*프로토콜 내 타입 메소드 선언
 
product Species {
    static func species() -> String
}
cs

 

- 프로토콜 상속

*프로토콜 상속과 구현
 
protocol Singing {
    func sing() {}
}
protocol Dancing {
    func dance() {}
}
protocol Entertaining : Singing, Dancing {
}
 
*프로토콜 상속 관계까지 고려해서 구현
 
struct Human : Entertaining
    func sing() {}
    func dance() {}
}
cs

 

- 프로토콜 내 프로퍼티

#프로토콜 내 프로퍼티 선언

*get/set 행위만 선언
*get 전용, get/set 모두
*set 전용은 없음
 
protocol HoldingBreath {
    var duration : Int { get set }
}
 
*타입 프로퍼티 선언 가능
cs

 

#프로토콜의 프로퍼티 구현

*저장 프로퍼티로 구현
 
struct MyStruct : HoldingBreath {
    var duration : Int
}
 
*계산 프로퍼티 구현
 
class MyClass : HoldingBreath {
    var duration : Int {
        get {
            return 0
        }
        set {}
    }
}
cs

 

- 프로토콜 내 Initializer

#프로토콜 내 Initializer 선언

protocol Named {
    init(name : String)
}
cs

 

#구현하기

*클래스 구현 시 required 추가
 
class Monster : Named {
    required init(name: String) {
        self.name = name
    }
}
 
*convenience initializer에도 required 추가
*struct에는 required 사용 안 함
 
struct Boss : Named {
    init(name : String) {}
}
cs

 

- 프로토콜 내 Failable Initializer

*프로토콜 선언
 
protocol Named {
    init?(name : String)
}
 
*Non-failable Initializer로 구현하기
 
class Monster : Named {
    required init(name : String) {}
}
 
*Failable Initializer로 구현하기
 
struct Boss : Named {
    init?(name : String) {}
}
cs

 

- 프로토콜 타입

#프로토콜을 타입으로 사용

*프로토콜을 타입으로 선언
*프로토콜 내 메소드, 프로퍼티만 사용 가능
 
var singingAnimal : Singing = Human()
singingAnimal.sing()
 
*다수의 프로토콜 타입
 
func entertain(who : Singing & Dancing) {
}
cs

 

- 클래스 전용 프로토콜

#클래스에서만 채택 가능

*class 키워드 사용
 
protocol MyProtocol : class {
}
 
*구조체, enum에서는 에러
*클래스에서만 채택, 구현 가능
*프로토콜 타입을 weak와 사용할 때
 
class MyClass : MyProtocol {
    weak var property : MyProtocol!
}
cs

 

2. extension

 

- extension

*타입을 나눠서 작성
*하나의 타입으로 동작
*기존에 작성된 타입(혹은 남이 작성한) 확장
*서로 다른 파일에 작성 가능
 
class Dog {
    func eat() { print("밥 먹기") }
}
extension Dog {
    func bike() { print("멍멍멍") }
}
var myDog = Dog()
myDog.eat()
myDog.bike()
cs

 

#extension으로 가능한 것

 *계산 프로퍼티

 *메소드

 *프로토콜

 *서브스크립트

 *nested type

 

#extension으로 불가능한 것

 *designated initializer

 *저장 프로퍼티

 

- 프로퍼티

#extension과 프로퍼티

extension Dog {
    //저장 프로퍼티 에러
 
    //계산 프로퍼티
    var everageLife : Int! {return 15}
cs

 

- Initializer

#Initializer 추가

*Designated Initializer 추가 불가
*Convenience Initializer 추가
 
class Dog {
    // Designated Initializer
    init() {}
}
 
extension Dog {
    convenience init(name : String) {
        self.init()
    }
}
cs

 

- 프로토콜

#프로토콜 채택 및 구현

*extension내 프로토콜 채택 구현
*프로토콜에는 Initializer가 없을 것
 
protocol Running {
    func run()
}
extension Dog : Runnig {
    func run() {
        print("뛰기")
    }
}
cs

 

3. 프로토콜 extension

 

- 프로토콜

#프로토콜 extension

 *프로토콜 extension에 구현 코드 작성 가능

 *프로토콜 채택으로 프로토콜 extension의 구현 코드 사용

 *다중 상속과 비슷한 효과

 *구조체/Enum 사용 시 중복 코드 문제 해결

 

#POP

 *POP(Protocol Oriented Programming)

 *구조체와 Protocol, extension 활용한 프로그래밍 기법

- 프로토콜 extension

#프로토콜과 프로토콜 확장

*프로토콜과 프로토콜 확장
 
protocol Movable { }
extension Movable {
    func move() {
        print("Go! go! go!")
    }
}
 
*프로토콜 채택, 객체를 이용한 호출
 
struct Human : Movable {}
var man = Human()
man.movel()
cs

 

#다중 프로토콜 채택

*다중 상속 효과
*기본 구현 재정의
 
class Superman : Movable, Flyable {
    func move() {
        print("Move Fast")
    }
}
var superaman = Superman()
superman.move()
superman.fly()    
cs

 

- 구조체와 프로토콜 Extension

#상속이 없는 구조체

*코드 중복이 발생하는 상황
 
struct Bird {
    func move() {
        print("이동하다")
    }
    func fly() {
        print("날다")
    }
}
struct Airplane {
    func move() {
        print("이동하다")
    }
    func fly() {
        print("날다")
    }
}
cs

 

#프로토콜 extension으로 코드 중복 제거

protocol Movable {}
extension Movable {
    func move() {
        print("이동하다")
    }
}
protocol Flyable {}
extension Flyable {
    func fly() {
        print("날다")
    }
}
struct Bird : Movable, Flyable {
}
struct Airplane: Movable, Flyable {
}
cs