[swift] 프로토콜 (protocol) / 확장 (extension)

Snyong·2023년 9월 29일

swift

목록 보기
9/10
post-thumbnail

Protocol?

  • protocol 은 어떤 약속(역할)을 정해놓은 것 → properties, method
  • 어떤 약속(역할)을 정해 놓은것이지 아직 구현된것은 아님

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.
In addition to specifying requirements that conforming types must implement, you can extend a protocol to implement some of these requirements or to implement additional functionality that conforming types can take advantage of.

protocol ClassPresident {
    var name: String {get}
    var className: String {get}
    
    func sayHello()
    func checkClassMember()
}

struct UnivPresidentStudnet: ClassPresident {
    var name: String
    var className: String
    
    func sayHello() {
        print("대학생: 인사")
    }
    
    func checkClassMember() {
        print("대학생: 인원 체크")
    }
}

struct HighSchoolPresidentSchool: ClassPresident {
    var name: String
    
    var className: String
    
    func sayHello() {
        print("고등학생: 인사")
    }
    
    func checkClassMember() {
        print("고등학생: 인원 체크")
    }
}

let jason = UnivPresidentStudnet(name: "Jason", className: "공대")
let jake = HighSchoolPresidentSchool(name: "Jake", className: "이과")

jason.sayHello()
jason.checkClassMember()

jake.sayHello()
jake.checkClassMember()

/*
 대학생: 인사
 대학생: 인원 체크
 고등학생: 인사
 고등학생: 인원 체크
 */


Protocol을 채택했지만 Protocol에서 있는 내용을 구현하지 않으면 경고창이 뜬다. Fix를 누르면 올바르게 구현할 수 있도록 아래 사진처럼 변경된다.

뒤에 붙은 get, set이 무엇인지는 공식문서에서 자세히 설명해주고 있다. {get}은 속성이 적어도 읽을 수 있어야 함을, {get set}은 속성이 읽고 쓸 수 있어야 함을 의미한다고 한다.

protocol이 왜 필요한가?

  • 다양한 객체에서 공통된 역할이 필요한 경우가 있다
  • 해당 역할을 프로토콜로 정의하고, 필요한 경우 각 객체에서 해당 프로토콜을 채택

한가지 객체에 대해서만 buy() 메소드를 정의할 때

struct Book {
    var name: String
}

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

let harrypotter = Book(name: "Harry Potter")
buy(harrypotter)

Purchasable 역할에 buy() 메소드를 정의할때

protocol Purchasable {
    var name: String {get set}
}

func buy(_ item: Purchasable) {
    print("I am buying \(item.name)")
}

struct Book: Purchasable {
    var name: String
    var author: String
}

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

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

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

let harryPotter = Book(name: "HarryPotter", author: "JK")
let topgun = Movie(name: "Top GUn", actors: ["Tom"])
let modelX = Car(name: "modelX", manufacturer: "Tesla")
let americano = Coffee(name: "ahah", strength: 5)

buy(harryPotter)
buy(topgun)
buy(modelX)
buy(americano)

/*
I am buying HarryPotter
I am buying Top GUn
I am buying modelX
I am buying ahah
*/

protocol 상속

  • protocol 은 상속 받을 수 있음
  • 클래스와 다르게 여러개 상속이 가능하여, 더 작고 명확하게 나눌 수 있음
  • 재사용성도 늘고, 테스트 가능성도 더 높아짐
protocol Payable {
    func calculatewages() -> Int
}

protocol Trainable {
    func train()
}

protocol Hasvacation {
    func takeVacation(days: Int)
}

protocol Employee: Payable, Trainable, Hasvacation { }

struct DeveloperEmployee: Employee {
    var name:String
    
    func calculatewages() -> Int {
        return 10_000_000
    }
    
    func train() {
        print("study hard")
    }
    
    func takeVacation(days: Int) {
        print("take \(days) days off")
    }
}

let choi = DeveloperEmployee(name: "Snyong")

choi.calculatewages()
choi.takeVacation(days: 3)
choi.train()

extension

  • 기존에 있던 타입에 기능을 추가할 수 있게 해줌
extension Int {
    func squared() -> Int {
        return self*self
    }
}

let number = 8
number.squared()

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

number.isEven

Protocol Extension

  • protocol은 어떤 역할에 대한 정의를 설명해주지만, 실제 구현은 제공해주지 않음
  • extension 은 기능에 대한 구현을 제공해주지만, 한가지 타입에만 적용됨
  • protocol extension은 두가지 단점을 보완할 수 있음
    protocol 에 기본 구현을 제공해줄 수 있음
    protocol 을 채택하는 여러 타입에 기능을 제공해줄 수 있음
extension Collection {
    func summarize() {
        print("There are \(count) members")
    }
}

let stringArray = ["AA", "bb", "cc"]
let numSet = Set([1,2,3,4,5])

stringArray.summarize()
numSet.summarize()

Protocol Oriented Programming

  • protocol 은 어떤 역할에 대한 정의를 제공
  • extension 은 어떤 타입에 구현을 제공
  • protocol extension 은 어떤 역할에 대한 기본 구현 제공
    → POP(Protocol Oriented Programming)이 가능
protocol Payable {
    func calculateWages() -> Int
}

protocol Trainable {
    func train()
}

protocol HasVacation {
    func takeVacation(days: Int)
}

extension Payable {
    func calculateWages() -> Int {
        return 10_000_000
    }
}

extension Trainable {
    func train() {
        print("study hard")
    }
}

extension HasVacation {
    func takeVacation(days: Int) {
        print("take \(days) days off")
    }
}

protocol Employee: Payable, Trainable, HasVacation { }

struct DeveloperEmployee: Employee {
    var name: String
}

let choi = DeveloperEmployee(name: "Jason")

choi.calculateWages()
choi.takeVacation(days: 3)
choi.train()


struct DesignerEmployee: Employee {
    var name: String
}

let jane = DesignerEmployee(name: "jane")
jane.calculateWages()
jane.takeVacation(days: 5)
jane.train()

0개의 댓글