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}은 속성이 읽고 쓸 수 있어야 함을 의미한다고 한다.
- 다양한 객체에서 공통된 역할이 필요한 경우가 있다
- 해당 역할을 프로토콜로 정의하고, 필요한 경우 각 객체에서 해당 프로토콜을 채택
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 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 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에 기본 구현을 제공해줄 수 있음
→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은 어떤 역할에 대한 정의를 제공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()