티스토리 뷰
프로토콜이란
- 특정 역할을 하기 위한 메서드, 프로퍼티, 기타 요구사항 등의 청사진
- ‘프로토콜을 준수한다’라는 것은 프로토콜의 요구사항을 모두 충족시키는 것
- 프로토콜은 정의를 하고 제시할 뿐 기능 구현을 하지 않음
프로토콜 채택
- protocol 키워드 사용
- 클래스가 다른 클래스를 상속받는다면, 클래스 이름 다음에 프로토콜 나열
protocol (프로토콜이름) {
(프로토콜 정의)
}
// 타입의 프로토콜 채택
Struct SomeStruct: AProtocol, BProtocol {
(구조체 정의)
}
Class SomeClass: SuperClass, AProtocol, BProtocoal {
(클래스 정의)
}
프로토콜 요구사항
- 프로토콜은 자신을 채택하면 프로퍼티나 메서드와 같은 기능들을 요구함
프로퍼티 요구
- 프로토콜은 자신을 채택한 타입이 어떤 프로퍼티를 구현해야 하는지 요구할 수 있음
- 그렇지만 그 프로퍼티의 종류를 요구하지 않음
- 다만 읽기 전용으로 할지, 읽고 쓰고 모두 가능하게 할지는 프로토콜이 정함
- 프로퍼티 요구사항은 항상 var 키워드를 사용한 변수 프로퍼티로 정의
protocol SomeProtocol {
var setTableProperty: String { get set } // 읽기 쓰기 모두 가능한 프로퍼티
var notNeedToBeSetTableProperty: String { get } // 읽기 전용 프로퍼티
}
protocol AnotherProtocol {
static var someTypeProperty: Int { get set } // 타입프로퍼티 요구
static var anotherTypeProperty: Int { get }
}
// Sendable 프로토콜과 프로토콜을 준수하는 클래스
protocol Sendable {
var from: String { get } // 읽기 전용
var to: String { get }
}
class Message: Sendable {
var sender: String
var from: String { // 읽기 전용
return self.sender
}
var to: String // 읽기, 쓰기 프로퍼티 구현해도 문제 없음
init(sender: String, receiver: String) {
self.sender = sender
self.to = receiver
}
}
class Mail: Sendable {
var from: String
var to: String
init(sender: String, receiver: String) {
self.from = sender
self.to = receiver
}
}
let message = Message(sender: "sender", receiver: "receiver")
print(message.to) // receiver
print(message.from) // sender
message.to = "tester"
// message.from = "test2" 에러, 쓰기 불가능
print(message.to) // tester
print(message.from) // sender
let mail = Mail(sender: "sender", receiver: "receiver")
print(mail.to) // receiver
print(mail.from) // sender
mail.to = "tester"
mail.from = "tester2"
print(mail.to) // tester
print(mail.from) // tester2
메서드 요구
- 특정 인스턴스 메서드나, 타입 메서드를 요구할 수도 있음
- 타입 메서드를 요구할 때는 static을 명시하나, 실제 구현할 때는 class를 사용해도 문제 없음
// Receiveable, Sendable 프로토콜을 준수하는 클래스
// 수신 기능
protocol Receiveable {
func received(data: Any, from: Sendable)
}
// 발신 기능
protocol Sendable {
var from: Sendable { get } // 타입으로서 프로토콜은, 프로토콜을 채택한 클래스의 인스턴스가 들어갈 수 있다는 것을 의미함. Sendable을 채택한 클래스가 from의 타입으로 들어갈 수 있음.
var to: Receiveable? { get }
func send(data: Any)
static func isSendableInstance(_ instance: Any) -> Bool
}
// 수신, 발신 가능한 클래스
class Message: Sendable, Receiveable {
// 발신 가능한 객체는 Sendable 프로토콜을 준수하는 타입의 인스턴스, 여기서는 자신
var from: Sendable {
return self
}
// 수신 가능한 객체는 Receiveable을 준수하는 타입의 인스턴스
var to: Receiveable?
// 메시지 발신
func send(data: Any) {
guard let receiver: Receiveable = self.to else {
print("There isn't a receiver of a message")
return
}
// 수신 가능한 인스턴스의 메서드 호출
receiver.received(data: data, from: self.from)
}
// 메시지 수신
func received(data: Any, from: Sendable) {
print("Message received \(data) from \(from)")
}
// 상속 가능한 메서드
class func isSendableInstance(_ instance: Any) -> Bool {
if let sendableInstance: Sendable = instance as? Sendable {
return sendableInstance.to != nil
}
return false
}
}
class Mail: Sendable, Receiveable {
// 발신 가능한 객체는 Sendable 프로토콜을 준수하는 타입의 인스턴스, 여기서는 자신
var from: Sendable {
return self
}
// 수신 가능한 객체는 Receiveable을 준수하는 타입의 인스턴스
var to: Receiveable?
// 메시지 발신
func send(data: Any) {
guard let receiver: Receiveable = self.to else {
print("There isn't a receiver of the mail")
return
}
// 수신 가능한 인스턴스의 메서드 호출
receiver.received(data: data, from: self.from)
}
// 메시지 수신
func received(data: Any, from: Sendable) {
print("Mail received \(data) from \(from)")
}
// 상속 불가능한 메서드
static func isSendableInstance(_ instance: Any) -> Bool {
if let sendableInstance: Sendable = instance as? Sendable {
return sendableInstance.to != nil
}
return false
}
}
// 인스턴스 생성
let myPhoneMessage: Message = Message()
let yourPhoneMessage: Message = Message()
// 수신 받을 인스턴스 없음
myPhoneMessage.send(data: "test") // There isn't a receiver of a message
// Message는 수발신 다 가능
myPhoneMessage.to = yourPhoneMessage
myPhoneMessage.send(data: "Hello") // Message received Hello from Message
// 메일 인스턴스 생성
let myMail = Mail()
let yourMail = Mail()
myMail.send(data: "Hi") // There isn't a receiver of the mail
myMail.to = yourMail
myMail.send(data: "to your mail") // Mail received to your mail from Mail
myMail.to = myPhoneMessage
myMail.send(data: "to my phone message") // Message received to my phone message from Mail
// String은 Sendable 프로토콜을 준수하지 않음
Mail.isSendableInstance("string") // false
// myPhoneMessage는 프로토콜 준수함
Message.isSendableInstance(myPhoneMessage) // true
// yourPhoneMessage는 프로퍼티 설정이 되지 않음, 프로퍼티 준수 하지 않음
Message.isSendableInstance(yourPhoneMessage) // false
가변 메서드 요구
- 메서드가 인스턴스 내부의 값을 변경할 필요가 있음
- 인스턴스 메서드에서 자신 내부의 값을 변경하고자 할때는 mutating func 명시
- 어떤 타입이든 간에 인스턴스 내부의 값을 변경해야하는 메서드를 요구하려면 mutating 명시
- 클래스 구현에서는 mutating 키워드 써주지 않아도 됨
protocol Resettable {
mutating func reset()
}
class ClassPerson: Resettable {
var name: String?
var age: Int?
func reset() {
self.name = ""
self.age = 0
}
}
struct StructPerson: Resettable {
var name: String?
var age: Int?
mutating func reset() {
self.name = ""
self.age = 0
}
}
- 만약 Resettable 프로토콜에서 가변 메서드를 요구하지 않는다면, mutating 메서드는 구현 불가능
protocol Resettable {
func reset()
}
class ClassPerson: Resettable {
var name: String?
var age: Int?
func reset() {
self.name = ""
self.age = 0
}
}
struct StructPerson: Resettable {
var name: String?
var age: Int?
func reset() {
// self.name = ""
// self.age = 0
}
}
'programming > Swift' 카테고리의 다른 글
[Swift/iOS] UIAlertController를 리팩토링하는 2가지 방법, Helper 클래스와 프로토콜 접근 (0) | 2023.03.11 |
---|---|
[Swift/iOS] Swift 튜토리얼: MVVM 디자인 패턴의 소개(일부) (0) | 2022.10.26 |
[Swift/iOS] 인스턴스 메소드와 타입메소드, static 메소드와 class 메소드 (0) | 2022.10.25 |
[Swift/iOS] 제네릭(2) (0) | 2022.10.21 |
[Swift/iOS] 제네릭(1) (0) | 2022.10.21 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- ios
- 강한참조순환
- 강한 참조 순환
- 메모리 안정성
- 디자인패턴
- authorizationCode
- identity Token
- SWIFT
- 토큰저장
- Entity
- core data
- 캡쳐리스트
- CoreData
- unowned
- autoclosure
- 회원가입
- 클로저 축약
- Core Data Stack
- ASAuthorizationAppleIDCredential
- weak
- 클로저
- 클로저 강한 참조
- object
- Persistent Container
- inout 파라미터 메모리 충돌
- 자동클로저
- 클로저표현
- context
- escaping closrue
- Delegate 패턴
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
글 보관함