11일차 - 21.06.18

수킴·2021년 6월 18일
0

100DaysOfSwift

목록 보기
12/37
post-thumbnail

학습키워드

  • protocols
  • extensions
  • protocol extensions

1. Protocols

프로토콜은 어떤 속성과 메서드가 있어야하는지 설명하는 방법입니다.

protocol Identifiable {
    var id: String { get set }
}

protocol editProtocol {
    var name: String { get }
}

struct User: Identifiable {
    var id: String
}

func displayID(thing: Identifiable) {
    print("My ID is \(thing.id)")
}

let user = User(id: "test")
displayID(thing: user)

// 실행결과
My ID is test
  • 프로토콜을 사용하는 타입을 (프로토콜 채택 또는 준수한다고 합니다)
  • 프로토콜의 속성은 get 읽기 , set 쓰기 할 수 있어야합니다. (get 읽기만 가능하도록 할 수 있습니다.)
  • 프로토콜은 자체적으로 인스턴스를 만들 수 없습니다. 프로토콜은 우리가 직접 만들고 사용할 수 있는 것이 아니라 우리가 원하는 것에 대한 설명입니다.

프로토콜이 필유한 이유는 무엇일까?

프로토콜을 사용하면 구조체,클래스 및 열거형등이 작동해야 하는 방식을 정의할 수 있습니다. 이러한 규칙을 적용하여 타입이 프로토콜을 준수한다고 말할 때 해당 타입들은 프로토콜의 속성과 메서드를 가지고 있습니다.

이러한 점을 이용해서 여러 타입이 프로토콜만 준수한다면 속성 및 메서드를 자유롭게 사용할 수 있습니다.

struct Movie: Purchaseable {
    var name: String
    var actors: [String]
}

struct Car: Purchaseable {
    var name: String
    var manufacturer: String
}

struct Coffee: Purchaseable {
    var name: String
    var strength: Int
}

func buy(_ item: Purchaseable) {
    print("I'm buying \(item.name)")
}

2. Protocol inheritance

프로토콜도 상속이 가능합니다. 하지만 클래스의 상속과 달리 여러프로토콜에서 상속 할 수 있습니다.

protocol Payable {
    func calculateWages() -> Int
}

protocol NeedsTraining {
    func study()
}

protocol HasVacation {
    func takeVacation(days: Int)
}

protocol Employee: Payable, NeedsTraining, HasVacation { }

프로토콜이 상속이 필요한 이유가 무엇일 까?

  1. 프로토콜 상속을 사용하는 이유 중 하나는 공통적인 부분을 하나의 단위로 결합하는 것입니다.

    예를 들어,

    • 모든 제품에는 가격과 무게가 있다.
    • 모든 컴퓨터에는 cpu,memory, 저장공간이 있다.
    • 모든 노트북에는 화면 크기가 있다.
    // MARK: - 상속을 사용하지 않은 경우
    protocol Computer {
        var price: Double { get set }
        var weight: Int { get set }
        var cpu: String { get set }
        var memory: Int { get set }
        var storage: Int { get set }
    }
    
    protocol Laptop {
        var price: Double { get set }
        var weight: Int { get set }
        var cpu: String { get set }
        var memory: Int { get set }
        var storage: Int { get set }
        var screenSize: Int { get set }
    }
    
    // MARK: - 상속을 사용한 경우
    protocol Product {
        var price: Double { get set }
        var weight: Int { get set }
    }
    
    protocol Computer: Product {
        var cpu: String { get set }
        var memory: Int { get set }
        var storage: Int { get set }
    }
    
    protocol Laptop: Computer {
        var screenSize: Int { get set }
    }
    • 컴퓨터와 노트북의 많은 속성이 중복되어 사용됩니다. 중복되는 부분을 더 작은 부분으로 나누고 재조립하면 코드가 훨씬 더 간단하고 유연해집니다.
  2. 프로토콜 상속을 사용하는 두번째 이유는 추가제한을 추가하기 위해서입니다.

    예를 들어, Equatable, Comparable 프로토콜이 있는 경우 , 등호 같은 경우에 두가지 프로토콜을 채택하여 추가제한을 둘 수 있습니다.

3. Extensions

확장을 사용하면 기존 타입에 메서드를 추가하여 처음 설계되지 않은 작업을 수행할 수 있습니다.

사용방법은 extension 키워드를 사용합니다.

확장에서는 저장프로퍼티를 사용할 수 없습니다. 그러나 연산프로퍼티는 사용 가능합니다.

extension Int {
    var isEven: Bool {
        return self % 2 == 0
    }

    func squared() -> Int {
        return self * self
    }
}

let number = 9

number.isEven // false
number.squared() // 81

언제 확장기능을 사용해야 할까?

확장을 사용하면 Apple 또는 다른 사람이 작성한 타입을 수정하는데 유용합니다.

또한 가독성을 향상시킬 수 있습니다. 아래 분류방식을 자주 사용합니다.

  • conformance grouping : 프로토콜을 채택할 때 확장내에 필요한 프로토콜 속성 및메서드를 추가하는 것을 통해 가독성에 도움이 됩니다.
  • purpose grouping : 관련된 작업들에 대한 속성 및 메서드를 확장내에 정의하는 것입니다.

4. Protocol extensions

프로토콜은 어떤 메서드가 있어야 하는지에 대해 설명할 수 있지만 내부의 코드를 제공하지는 않습니다.

확장은 메서드 내부의 코드는 제공하지만 확장을 선언한 타입에만 영향을 미칩니다. 여러 타입에 동시에 메서드를 추가할 수 없습니다.

→ 프로토콜 확장을 사용하면 두가지 문제를 해결할 수 있습니다.

let pythons: [String] = ["Eric", "Graham", "John", "Michael", "Terry", "Terry"]
let beatles: Set<String> = Set(["John", "Paul", "George", "Ringo"])

extension Collection {
    func summarize() {
        print("There are \(count) of us:")

        for name in self {
            print(name)
        }
    }
}

pythons.summarize()
beatles.summarize()
  • 배열과 세트 모두 Collection프로토콜을 따르므로 Collection을 확장을 하면 두가지 모두 summarize() 메서드를 사용할 수 있습니다.

프로토콜의 확장은 언제 유용할 까?

프로토콜 확장은 스위프트의 여러곳에서 사용되며, 이러한 특징으로 인해 프로토콜 지향프로그래밍 언어라고 불리기도 합니다. 직접 기능을 추가하는 데 사용합니다. 즉, 많은 구조체와 클래스에 해당 기능을 복사 할 필요가 없습니다.

5. Protocol-oriented programming (P. O. P)

프로토콜확장은 자체 프로토콜 메서드에 대한 기본 구현을 제공할 수 있습니다.(간단히, 프로토콜 메서드 내부의 코드를 정의할 수 있습니다.) → 이를 통해 타입이 프로토콜을 쉽게 준수할 수 있습니다.

P.O.P : 프로토콜지향프로그래밍 (프로토콜 및 프로토콜 확장을 중심으로 코드를 작성하는 방식)

protocol Identifiable {
    var id: String { get set }
    func identify()
}

extension Identifiable {
    var test: String {
        let doubleId = id + id
        return doubleId
    }
    func identify() {
        print("My ID is \(id).")
    }
}

struct User: Identifiable {
    var id: String
}

let twostraws = User(id: "twostraws")
twostraws.id //"twostraws"
twostraws.test //"twostrawstwostraws"
twostraws.identify() // My ID is twostraws.
  • private 접근 제어자

프로토콜 지향프로그래밍과 객체지향프로그래밍의 차이점은 무엇일 까?

POP에서는 프로토콜을 구성하여 기능을 구축하는 것을 선호하는 반면 OOP에서는 클래스 상속을 통해 기능을 구축하는 것을 선호합니다.

두가지 프로그래밍의 차이점은 사고방식의 차이입니다. POP에서는 프로토콜 확장기능에 크게 의존하여 프로토콜에서 많은 동작을 얻는 타입을 빌드합니다. 이를 통해 많은 타입에서 기능을 더 쉽게 공유 할 수 있으므로 코드를 많이 작성하지 않고도 더 크고 강력한 소프트웨어를 빌드 할 수 있습니다.

링크

100 Days of Swift - Day 11 - Hacking with Swift

profile
iOS 공부 중 🧑🏻‍💻

0개의 댓글