-
Swift4: Protocol Oriented Programming - 6.프로토콜지향 프로그래밍POP 2021. 2. 17. 23:44
6장 프로토콜지향 프로그래밍
5장의 요구사항을 프로토콜지향 설계로 다시 작성한다.
프로토콜지향 프로그래밍 언어의 스위프트
프로토콜은 컴포지션(다중 채택)이 가능하기 때문에 5장에서와는 달리 지상/공중/해상 범주에 필요한 프로토콜들을 나눌 수 있다. 프로토콜 컴포지션, 상속, 확장을 이용하면 코드를 더욱 간결하고 안전성있게 작성할 수 있다.
protocol Vehicle { var hitPoints: Int {get set} } // 모든 이동수단에서 같은 기능을 하는 메소드를 확장으로 구현 extension Vehicle { mutating func takeHit(amount: Int) { hitPoints -= amount } func hitPointsRemaining() -> Int { return hitPoints } func isAlive() -> Bool { return hitPoints > 0 ? true : false } }
다음과 같이 이동수단의 protocol을 정의하고 같은 기능을 하는 메소드를 확장을 통해 구현한다.
protocol AirVehicle: Vehicle { var airAttack: Bool {get} var airMovement: Bool {get} var airAttackRange: Int {get} func doAirAttack() func doAirMovement() }
Vehicle 프로토콜을 상속받는 land/air/sea vehicle 프로토콜을 정의한다. 각 프로토콜에는 해당 타입에 관한 프로퍼티와 메소드만을 포함한다.
위에서 프로토콜의 프로퍼티를 get 속성으로만 정의하는데 이는 해당 프로퍼티를 상수로 정의하겠다는 것을 의미한다. 이를 통해 외부에서 프로퍼티 값을 변경하지 못하게 할 수 있다.
struct Tank: LandVehicle { var hitPoints = 68 let landAttack = true let landMovement = true let landAttackRange = 5 func doLandAttack() { print("Tank Attack") } func doLandMovement() { print("Tank Move") } }
다음은 해당 프로토콜을 채택하여 구현한 구조체이다. 프로토콜지향 프로그래밍에서는 값 타입을 권고하기 때문에, struct로 구현하였다. (강제는 아님)
위 구조체는 디폴트 이니셜라이저를 사용할 수 있으며, 프로퍼티를 상수로 선언할 수 있다.
for (index, vehicle) in vehicles.enumerated() { if let vehicle = vehicle as? AirVehicle { print("vehicle at \(index) is Air") } if let vehicle = vehicle as? LandVehicle { print("vehicle at \(index) is Land") } if let vehicle = vehicle as? SeaVehicle { print("vehicle at \(index) is Sea") } }
또한, 해당 프로토콜을 채택한 객체들을 사용할 때에는 다음과 같이 형 변환을 통하여 사용할 수 있다.
프로토콜지향 프로그래밍과 객체지향 프로그래밍 요약
-
차이점
- 프로토콜지향 설계는 프로토콜로 시작, 객체지향 설계는 슈퍼클래스로 시작
- 프로토콜지향 설계에서는 참조 타입보다는 값 타입을 사용
-
공통점
단일 인터페이스를 사용하여 서로 다른 타입 간의 상호작용을 위해 다형성을 사용
객체지향 프로그래밍과 프로토콜지향 프로그래밍의 차이점
깨끗한 코드: 읽기 쉽고 이해하기도 쉬운 코드
안전한 코드: 깨지기 어려운 코드 - 코드를 조금만 수정했는데 전체적으로 에러 팝업이 발생하지 않도록
-
프로토콜, 프로토콜 확장과 슈퍼클래스
Vehicle 슈퍼클래스는 인스턴스를 생성할 수 있는 완전한 타입이다. 하지만 이번에는 Vehicle 인스턴스를 직접적으로 생성하는 경우는 없었다.
프로토콜지향 설계 방식에서는 정의부와 구현부를 분리하고, 요구사항을 더욱 구체적인 프로토콜로 나눠 타입이 필요하지 않은 기능을 상속하는 것을 막을 수 있었다.
서브클래스를 이용해서 구현하는 경우는 슈퍼클래스의 구조를 개발자가 명확히 이해하고 있어야 한다. 서브클래스에서 무언가를 설정하는 것을 잊어버리더라도 컴파일러는 어떠한 경고도 하지 않고, 애플리케이션은 의도대로 동작하지 않을 것이다.
코드
참고 문헌
https://book.naver.com/bookdb/book_detail.nhn?bid=14107671
'POP' 카테고리의 다른 글
Swift4: Protocol Oriented Programming - 7.스위프트에서 디자인 패턴 적용 - (2) 구조 패턴 (0) 2021.02.24 Swift4: Protocol Oriented Programming - 7.스위프트에서 디자인 패턴 적용 - (1) 생성 패턴 (0) 2021.02.19 Swift4: Protocol Oriented Programming - 5.객체지향 프로그래밍 (0) 2021.02.16 Swift4: Protocol Oriented Programming - 4.제네릭 (0) 2021.02.15 Swift4: Protocol Oriented Programming - 3.확장 (0) 2021.02.15 -