애플에서는 swift 는 POP ( Protocol Oriented Programing ) 언어라고 언급한 만큼 프로토콜의 개념은 중요한거 같습니다.
하지만, 저 같은 경우는 실제 코드를 작성 할 때, 습관적인건지.. 스킬이 부족한건지… 필요성을 못 느끼는건지.. 잘 활용을 못 해온거 같습니다.
프로토콜에 대해 이야기를 나눌 사항이 너무 다양하기 때문에, Swift Language Guide 문서 토대로 기초적인 내용부터 확인하겠습니다.
Protocol 이란?
네트워크쪽 공부를 하신 분들은 통신 규약으로 프로토콜을 들으셨을겁니다. 개인적으로 네트워크 수업의 첫번 째 고비였었던 기억이 있네요..
프로토콜은 “컴퓨터들 간의 원활한 통신을 위해 지키기로 약속한 규약” 이라는 사전적 의미를 지니고 있습니다.
swift의 프로토콜 또한 위 의미와 비슷합니다!
swift의 프로토콜은 개발자가 새로운 객체를 정의 할 때, 프로퍼티 나 메소드 구현을 잊지 않게 끔하는 일종의 정의서라 생각합니다.
그렇기 때문에 프로토콜 내에는 메소드, 프로퍼티, 이니셜라이져가 정의가 되어있으나, 구현은 되어 있지 않습니다. 정의 된 프로토콜을 구조체, 클래스, 열거형은 채택하여 준수하면, 반드시 구현을 해야합니다.
저의 말하기 능력이 부족하여 당연히 이해가 안되실겁니다! 차차 코드를 보시면서 같이 느껴보시죠!
Protocol 사용
protocol 정의 및 채택
protocol InfoPrintable {
}
class Person {
}
struct Work: InfoPrintable {
}
enum Gender: InfoPrintable {
}
class Developer: Person, InfoPrintable {
}
∙ protocol 은 위와 같이 정의 할 수 있다.
∙ class, struct, enum 모두 protocol을 채택 할 수 있다.
∙ Develpoer class 와 같이 상속이 있는 경우 상속을 제일 앞에 작성해주며, 뒤에 채택 프로토콜을 작성한다.
∙ 프로토콜은 상속과 달리 다중 채택이 가능하다.
∙ 네이밍은 보통 ~able, ~ing, ~delegate 형식으로 한다.
protocol 준수
protocol InfoPrintable {
var info: String { get }
func infoPrint()
}
class Developer: Person, InfoPrintable {
var info: String
func infoPrint() {
print(info)
}
init(_ name: String, _ mainLanguage: DevelopLanguage) {
self.info = "name : \(name) , mainLanguage : \(mainLanguage)"
}
}
struct Work: InfoPrintable {
var info: String
func infoPrint() {
print(info)
}
}
enum DevelopLanguage: InfoPrintable {
case java, python, swift
var info: String {
switch self {
case .java:
return "java language"
case .python:
return "python language"
case .swift:
return "swift language"
}
}
func infoPrint() {
print(info)
}
}
∙ protocol 은 프로퍼티를 정의 할 수 있으며, 반드시 gettable, settalbe 인지를 명시해줘야 한다. 위 예제 같은 경우 enum은 gettable 프로퍼티 밖에 가지지 못하여, protocol 프로퍼티 또한 gettable로 정의하였습니다.
∙ static 키워드를 통해 타입프로퍼티 또한 정의 가능
∙ 메소드를 정의 할 수 있으나, body 구현부까지는 정의가 불가능하다. 위 예제에서는 파라미터, 반환값이 없으나 필요 시 파라미터, 반환 값 또한 명시 할 수 있다.
∙ 이니셜라이져 정의 가능
∙ protocol 을 채택한 타입들은 protocol 요구사항에 맞게 반드시 정의해줘야하며, 프로토콜을 준수한다라고 한다.
타입으로써 protocol
var infoPrintables: [InfoPrintable]
let developer = Developer("Kim", .swift)
let work = Work(info: "Develop App")
let developLanguage = DevelopLanguage.python
infoPrintables = [developer, work, developLanguage]
infoPrintables.forEach{ infoPrintType in
infoPrintType.infoPrint()
}
// name : Kim , mainLanguage : swift
// Develop App
// python language
∙ 프로토콜 또한 하나의 타입으로 사용 가능하다! 타입 사용이 허용되는 모든 곳에 프로토콜을 사용 할 수 있다.
∙ 함수, 메소드, 이니셜라이저의 파라미터 혹은 반환 타입
∙ 상수, 변수, 프로퍼티의 타입
∙ 배열, 사전 등의 아이템 타입
∙ is, as!, as? 활용 할 수 있습니다.
protocol Extensions
위에서 Developer, Work, DevelopLanguage 타입은 protocol을 준수하기 위해 같은 구문이지만, infoPrint()를 반복적으로 작성하였습니다.
여기서 ! 눈살을 찌푸리시거나 , 저를 욕하셔야합니다.. 해당 부분은 프로토콜 확장을 통해 아래와 같이 기본 구현이 가능합니다.
protocol InfoPrintable {
var info: String { get }
func infoPrint()
}
extension InfoPrintable {
func infoPrint() {
print(info)
}
}
class Developer: Person, InfoPrintable {
var info: String
func infoPrint() {
print("[Developer Info]")
print(info)
}
init(_ name: String, _ mainLanguage: DevelopLanguage) {
self.info = "name : \(name) , mainLanguage : \(mainLanguage)"
}
}
struct Work: InfoPrintable {
var info: String
// func infoPrint() {
// print(info)
// }
}
enum DevelopLanguage: InfoPrintable {
case java, python, swift
var info: String {
switch self {
case .java:
return "java language"
case .python:
return "python language"
case .swift:
return "swift language"
}
}
// func infoPrint() {
// print(info)
// }
}
기존 Developer, Work, DevelopLanugage 의 infoPrint 주석처리 하여도 오류가 나지 않습니다. Developer와 같이 기본 구현을 따르고 싶지 않다면 재정의도 가능합니다.
infoPrintables.forEach{ infoPrintType in
infoPrintType.infoPrint()
}
// [Developer Info]
// name : Kim , mainLanguage : swift
// Develop App
// python language
위 예제에서 선언한 infoPrintables 을 infoPrint 해주면 재정의한 Developer 이외 결과는 동일합니다.
정리
간단한 예제를 통해 프로토콜을 알아봤습니다. 저 또한 공부를 위해 여러가지 자료를 확인하였는데, 이외에도 프로토콜의 활용은 다양합니다.. 하지만, 실무 및 프로젝트에서 어떻게 효율적으로 활용 할 지는 사실 크게 와닿지 않습니다..
지금까지는 느낀 부분은 프로토콜을 통해 기능적인 부분을 첨가 할 수 있다? 위 예제와 같이 InfoPrintable 정의해놓으면, 타입의 정보를 프린트 해야하는 타입은 채택만 하면 되니..
매트릭스에서 네오한테 쿵푸, 태권도, 여러 무술을 단순히 주입하면 네오가 1초만에 무술들 하는 것과 같이 말이죠
POP, 델리게이트 패턴 등과 같이 추가적인 프로토콜 내용도 틈틈히 올리도록 하겠습니다!
오늘도 고생 많으셨습니다 :)
참고자료
https://jusung.gitbook.io/the-swift-language-guide/language-guide/21-protocols
https://www.youtube.com/watch?v=ZBqbuQzmN4o
'iOS & Swift' 카테고리의 다른 글
Swift - lazy 키워드 (0) | 2023.03.13 |
---|---|
iOS - Xcode *.xcuserstate , .gitignore 반영되지 않는 경우 (0) | 2023.03.09 |
iOS - AutoLayout, Autoresizing는 무엇인가 (0) | 2023.02.24 |
메소드 체이닝 (0) | 2023.01.04 |