Swift: Protocol Oriented Programming / 프로토콜 지향 프로그래밍

Wooyo·2023년 10월 24일
0
post-thumbnail

1. Swift

  • 클래스로 구현된 타입은 별로 없고 대부분 구조체로 기본 타입이 구현
  • 구조체는 상속이 되지 않음 -> 프로토콜과 익스텐션의 힘
  • 익스텐션 : 기존 타입의 기능을 확장
  • 프로토콜 : 프로토콜을 채택한 타입이 원하는 기능을 강제로 구현

2. 프로토콜 초기구현

  • 무언가 보내고 받을 수 있는 프로토콜을 정의하고 extension을 통해 기능을 구현하기
  • 익스텐션을 통한 프로토콜의 실제 구현
// 수신
protocol Receiveable {
	func received(data: Any, from: Sendable)
}

extension Receiveable {
	// 메시지 수신
    func received(data: Any, from: Sendable) {
    	print("\(self) received \(data) from \(from)") 
    }
}

// 발신
protocol Sendable {
	var from: Sendable { get }
    var to: Receiveable? { get }
    
    func send(data: Any)
    static func isSendableInstance(_ instance: Any) -> Bool
}

extension Sendable {
	// 발신은 발신 가능한 객체, Sendable protocol을 준후하는 타입의 인스턴스
    var from: Sendable {
    	return self
    }
    
    // 발신
    func send(data: Any) {
    	guard let receiver: Receiveable = self.to else { 
            print("Message has no receiver")
            return
        }

        // 수신 가능한 인스턴스의 received 메서드를 호출합니다.
        receiver.received(data: data, from: self.from) 
    }
    
    static func isSendableInstance(_ instance: Any) -> Bool {
    	if let sendableInstance: Sendable = instance as? Sendable {
        	return senableInstance.to != nil
        }
        return false
    }
}

// 수신, 발신이 가능한 Message 클래스 
class Message: Sendable, Receiveable {
    var to: Receiveable?
}

// 수신, 발신이 가능한 Mail 클래스 
class Mail: Sendable, Receiveable {
    var to: Receiveable?
}

// 두 Message 인스턴스를 생성
let myPhoneMessage: Message = Message() 
let yourPhoneMesssage: Message = Message()

// 아직 수신받을 인스턴스가 없습니다.
myPhoneMessage.send(data: "Hello") // Message has no receiver

// Message 인스턴스는 발신과 수신이 모두 가능하므로 메시지를 주고 받을 수 있습니다. 
myPhoneMessage.to = yourPhoneMesssage
myPhoneMessage.send(data: "Hello") // Message received Hello from Message

// Mail 인스턴스를 두 개 생성합니다.
let myMail: Mail = Mail()
let yourMail: Mail = Mail()

myMail.send(data: "Hi") // Mail has no receiver

// Message와 Mail 모두 Sendable과 Receiveable 프로토콜을 준수하므로 
// 서로 주고 받을 수 있습니다.
myMail.to = yourMail
myMail.send(data: "Hi") // Mail received Hi from Mail

myMail.to = myPhoneMessage
myMail.send(data: "Bye") // Message received Bye from Mail

// String은 Sendable 프로토콜을 준수하지 않습니다. 
Message.isSendableInstance("Hello") // false

// Message와 Mail은 Sendable 프로토콜을 준수합니다. 
Message.isSendableInstance(myPhoneMessage) // true

// yourPhoneMessage는 to 프로퍼티가 설정되지 않아서 보낼 수 없는 상태입니다.
Message.isSendableInstance(yourPhoneMesssage) // false
Mail.isSendableInstance(myPhoneMessage) // true
Mail.isSendableInstance(myMail) // true

class Mail: Sendable, Receiveable {
    var to: Receiveable?
    func send(data: Any) {
        print("Mail의 send 메서드는 재정의되었습니다.")
    }
}

let mailInstance: Mail = Mail()
mailInstance.send(data: "Hello") // Mail의 send 메서드는 재정의되었습니다.

3. 기본 타입 확장

  • 초기구현을 통해 기본 타입을 확장하여 내가 원하는 기능을 공통적으로 추가해 볼 수 있음
protocol SelfPrintable {
    func printSelf()
}

extension SelfPrintable {
    func printSelf() {
        print(self)
    }
}

extension Int: SelfPrintable { }
extension String: SelfPrintable { }
extension Double: SelfPrintable { }

1024.printSelf() // 1024 
3.14.printSelf() // 3.14 
"Jimin".printSelf() // "Jimin"
profile
Wooyo의 개발 블로그

0개의 댓글