[iOS] Protocol Oriented Programming

r1verfuture·2022년 4월 14일
0

iOS

목록 보기
22/30

Protocol Oriented Language

  • 프로토콜 지향 언어
  • ex. Swift

Swift

  • Swift 의 표준 라이브러리에서 타입 정의 부분을 보면 대부분이 구조체로 구현되어 있는 것을 볼 수 있다. (클래스로 구현된 타입도 있기는 하지만 드물다.)
  • Swift 가 상속 가능한 클래스 대신 상속 불가능한 구조체로도 다양한 공통 기능 구현이 가능했던 이유 : 프로토콜 & 익스텐션
// MARK: [코드 1] 익스텐션을 사용하지 않은 프로토콜 예시
protocol Talkable {
	var topic : String { get set }
    func talk(to : Self)
}

struct Person : Talkable {
	var topic : String // Talkable 프로토콜을 채택했기 때문에 준수해야 하는 프로퍼티
    var name : String // Person 구조체에 따로 정의한 프로퍼티
    
    func talk(to : Person) {
    	print("\(to.name) 에게 \(topic) 에 대해 말하는 \(name)")
    }
}

struct Bear : Talkable {
	var topic : String // Talkable 프로토콜을 채택했기 때문에 준수해야 하는 프로퍼티
    
    func talk(to : Bear) {
    	print("\(topic) 에 대해 말하는 곰돌이")
    }
}
  • [코드 1] : 채택한 프로토콜 안에 정의된 것들은 모두 구현해주어야 하기 때문에 프로토콜을 채택할 때마다 'talk' 메소드를 매번 구현해줘야 하는 번거로움이 있다.
// MARK: [코드 2] 익스텐션을 사용한 프로토콜 예시
protocol Talkable {
	var topic : String { get set }
    func talk(to : Self)
}

// 익스텐션 안에 프로토콜 초기 구현
extension Talkable {
	func talk(to : Self) {
    	print("\(to.name) 에게 \(topic) 에 대해 말하는중 ~")
    }
}

struct Person : Talkable {
	var topic : String // Talkable 프로토콜을 채택했기 때문에 준수해야 하는 프로퍼티
    var name : String // Person 구조체에 따로 정의한 프로퍼티
}

struct Bear : Talkable {
	var topic : String // Talkable 프로토콜을 채택했기 때문에 준수해야 하는 프로퍼티
}

let r1verfuture = Person(topic : "iOS", name : "r1verfuture")
let r2verfuture = Person(topic : "Swift", name : "r2verfuture")

r1verfuture.talk(to : r2verfuture) // "r2verfuture 에게 iOS 에 대해 말하는중 ~" 이라고 출력된다.
r2verfuture.talk(to : r1verfuture) // "r1verfuture 에게 Swift 에 대해 말하는중 ~" 이라고 출력된다.
  • [코드 2] : [코드 1] 과는 다르게 익스텐션으로 'Talkable' 프로토콜을 확장한 다음 확장한 내부에 'talk' 메소드를 구현해주었다.
  • 프로토콜을 확장한 내부에 메소드 구현부를 넣어주면 해당 프로토콜을 채택한 타입 내부에 해당 메소드를 구현해주지 않아도 문제없다.
  • 만약에 프로토콜 초기 구현과 다르게 동작해야 하는 경우에는 재정의해주기만 하면 된다. ([코드 3] 참고)
// MARK: [코드 3] 익스텐션을 사용해서 프로토콜 메소드 정의 후 그 메소드를 재정의하는 예시
protocol Talkable {
	var topic : String { get set }
    func talk(to : Self)
}

// 익스텐션 안에 프로토콜 초기 구현
extension Talkable {
	func talk(to : Self) {
    	print("\(to.name) 에게 \(topic) 에 대해 말하는중 ~")
    }
}

struct Bear : Talkable {
	var topic : String // Talkable 프로토콜을 채택했기 때문에 준수해야 하는 프로퍼티
    var name : String // Bear 구조체에 따로 정의한 프로퍼티
    
    // Talkable 프로토콜에 있던 기존 talk 함수 재정의
    func talk(to : Bear) {
    	print("\(to.name) 에게 \(topic) 에 대해 말하는중 ~")
    }
}

let whatso = Bear(topic : "Disney", name : "왓소")
let lotso = Bear(topic : "Toy Story", name : "랏소")

whatso.talk(to : lotso) // "랏소 에게 Disney 에 대해 말하는중 ~" 라고 출력된다.
lotso.talk(to : whatso) // "왓소 에게 Toy Story 에 대해 말하는중 ~" 라고 출력된다.
  • [코드 3] : 'Talkable' 프로토콜에 있던 기존 'talk' 메소드를 재정의해서 'Bear' 구조체에 구현해주었다.

Protocol Oriented Programming (POP) 을 쓰는 이유

  • 클래스는 참조 타입이기 때문에 참조 추적에 비용이 많이 발생한다.
  • 참조 타입과 비교했을 때 값 타입은 비용이 적게 들지만, 상속이 불가능해서 기능을 다시 구현해줘야 하는 한계를 없애버렸다.

참고

profile
#iOS #Swift #Developer #Python

0개의 댓글

관련 채용 정보