Swift

Swift - 프로토콜 (Protocol)

Goniii 2023. 8. 6. 19:04

프로토콜 (Protocol)

- 클래스, 구조체 또는 열거형과 같은 타입이 따라야 할 요구사항을 정의하는 일종의 추상 청사진

- 인터페이스와 유사하게 작동하며, 객체들 사이의 통신과 상호 작용을 위한 규칙 제공

- 클래스, 구조체, 열거형은 프로토콜을 채택(Adopt)하여 해당 프로토콜이 요구하는 속성과 메서드를 구현 

 

 

 

 

1. 프로토콜 선언

import UIKit

// 프로토콜은 약속
// 이름 설정은 **delegate, **able, **ing 등으로 설정
protocol Naming {
    
    // 우리는 이런 변수와 메서드를 가지고 있을 것입니다. 라고 약속하는 것
    var name : String { get set}
    
    func getName() -> String
}

- 'Naming' 프로토콜은 'name' 프로퍼티와 'getName' 메서드를 요구사항으로 가지고 있음

- 프로토콜 내 요구사항은 중괄호 '{ }' 가 없이 정의 됨 

- 프로퍼티에서 'get' 또는 'get set' 은 무조건 설정해야 함 

 

 

 

2. 프로토콜 채택, 준수(Implement)

struct Friend : Naming {
    var name: String
    
    func getName() -> String {
        "제 친구 이름은 \(self.name)"
    }
}

- 'Friend' 구조체에서는 'Naming' 프로토콜을 채택함

- 따라서 'Naming' 프로토콜의 'name', 'getName()' 을 반드시 구현해야 함

 

 

 

3. 프로토콜 준수한 구조체 사용

var myFriend = Friend(name: "홍길동")

print(myFriend.getName())

 

 


프로토콜 상속

- 하나 이상의 프로토콜을 다른 프로토콜에게 상속하는 개념

- 기존의 프로토콜을 기반으로 새로운 프로토콜을 정의하고, 기존 프로토콜에 정의된 요구사항들을 재사용 

 

 

 

1. 프로토콜 정의

import UIKit

// 프로토콜은 약속
// 이름 설정은 **delegate, **able, **ing 등으로 설정
protocol Naming {
    
    // 우리는 이런 변수와 메서드를 가지고 있을 것입니다. 라고 약속하는 것
    var name : String { get set}
    
    func getName() -> String
}

protocol Aging {
    var age : Int { get set}
}

protocol UserInformation : Naming, Aging{
    
}

- 'UserInformation' 프로토콜 : 'Naming', 'Aging' 프로토콜을 상속

 

 

2. 프로토콜 구현

class MyBestFriend : UserInformation{
    var name: String = "홍길동"
    
    func getName() -> String {
        "나의 bestFreind는 \(self.name)"
    }
    
    var age: Int = 22

}

- 'UserInformation' 프로토콜을 채택한 'MyBestFreind' 클래스 정의

- 'MyBestFreind' 는 'UserInformation' 프로토콜을 채택했기 때문에 해당 프로토콜에서 요구하는 'name', 'age', 'getName()' 메서드를 모두 구현해야 함

 

 

 


프로토콜 확장(Protocol Extension)

- 이미 정의된 프로토콜에 새로운 기능을 추가하거나 기존의 요구사항을 구현하도록 도움

- 프로토콜을 채택한 모든 타입에 대해 기본 구현을 제공 가능 

 

 

 

 

기본 Protocol

protocol Naming {
    
    var name : String { get set}
    
    func getName() -> String
}

 

 

 

기능 1. 프로토콜에 기본 구현 제공

 

Protocol 확장 (기본 구현)

extension Naming{
    func getName() -> String {
        return "제 이름은 \(self.name)입니다."
    }
}

struct Person : Naming{
    var name: String
}
var person = Person(name: "홍길동")
print(person.getName()) // 출력 : 제 이름은 홍길동 입니다.

- 'extenstion' 을 통해 'Naming' protocol을 확장함으로써 'getName()' 메서드를 기본 구현 제공 

- 'Naming' 프로토콜을 채택한 'Person' 구조체는 별도의 'getName()' 메서드를 구현하지 않아도 기본 구현이 사용 됨 

 

 

 

 

기능 2. 프로토콜에 새로운 기능 추가

// 프로토콜 확장 (새로운 기능 추가)
extension Naming{
    func address() -> String{
        return "저는 경기도에 살고 있습니다."
    }
}

struct Person : Naming{
    var name: String
}
var person = Person(name: "홍길동")
print(person.address())     // 저는 경기도에 살고 있습니다.

- 'Naming' 프로토콜에 'address()' 라는 새로운 메서드 추가

- 'Person' 구조체가 'Naming' 프로토콜을 채택하여 'address()' 메서드 사용 가능 

 

 

 

프로토콜 확장은 기존의 프로토콜을 수정하지 않고도 기능을 추가하거나 기본 구현을 제공할 수 있음

이를 통해 프로토콜과 타입들 사이의 강력한 결합도를 유지하면서도 코드 재사용성과 유지 보수성을 향상 시킬 수 있음

 

 

 

 

 

 


참고)

https://www.youtube.com/watch?v=ZBqbuQzmN4o 

https://www.youtube.com/watch?v=an1vLvTDIKw 

https://www.youtube.com/watch?v=D-zrCL7q-Eg 

 

728x90