Object Oriented Programming / 객체지향 프로그래밍
독립된 객체를 만들고, 서로 협력을 통해 다른 객체와 Message를 주고 받으며 소프트웨어를 구성하는 것
- | 설명 |
---|---|
Messaging | 다른 객체의 데이터나 프로시져가 필요할 때는 메세지로 요청을 하고, 메세지를 받는 객체는 스스로 처리 방법을 선택한다. |
Hiding of state-process (캡슐화) | 관련있는 데이터와 프로시져를 찾아서 묶고, 다른 객체가 내부를 건드리지 못하게 한다. (private을 우선 적용하라는 이유) |
Extreme late-binding | 메세지를 받는 객체는 그때 그때 달라질 수 있다. |
프로시저 : 데이터(상수)를 가지고 조건문, 반복문 등을 통해 일정한 절차를 수행하는 부분
메세지
를 받는 부분만 일관되게 유지된다면, 실제로 그걸 처리하는 코드는 바뀌어도 실행에 문제가 없다.메세지를 보내는 것 ≠ 메서드 호출
응답
하는 방식은 객체가 스스로 결정그리고, 객체지향의 정말 중요한 개념인
Subclassing
이라고도 하는데, 이능 기존에 구현되어있는 부모 클래스를 확장, 및 변형하는 것을 말한다.Override
/ Overriding
을 의미같이 학습하는 Eddy의 말을 빌려 한 줄로 말해보자면, 캡슐화 되어있는 서로 호환 가능한 세포들이, 서로 메세지를 주고 받으면서 더 큰 소프트웨어를 구성하는 방식
이라고 할 수 있겠다!
(참고 문서에 있는 Eddy 벨로그를 통해 더 정확히 이해할 수 있다.)
Protocol Oriented Programming / 프로토콜지향 프로그래밍
OOP의 단점을 보안한, Protocl을 통한 상속의 한계점을 탈피한 프로그래밍
1. 보다 유연한 프로그래밍
필요한 부분만 프로토콜로 분리할 수 있고, 다중 프로토콜을 구현할 수도 있다.
이 규칙을 Class / Struct / Enum 에 적용할 수 있어 OOP보다 유연한 프로그래밍이 가능하다.
2. 값 타입의 상속
Swift의 기본 타입(String
, Int
, Float
등)은 대부분 구조체로 구현이 되어있다.
Protocol과 Extension 사용시, 위처럼 상속이 되지 않는 타입들에게 공통된 기능
을 줄 수 있다.
3. 수평적인 기능 확장
Class는 하나의 상속만 가능하고 수직적인 구조를 고려하여야 하지만 Protocol은 마치 블럭처럼 기능을 추가할 수 있다.
4. OOP의 단점 보완
OOP는 상속을 통해 타입을 확장한다. 그로 인해 슈퍼클래스를 그대로 상속받아, 불필요한 프로퍼티들을 갖게 된다.
상속
구조를 사용하기 위해, 값 타입으로 정의해도 되는 모델들을 참조타입으로 정의해야 하기도 한다.
하지만, POP는 슈퍼클래스와 서브클래스의 사이가 독립적이다. 값/참조 타입을 모두 사용할 수 있다.
// 아래와 같은 프로토콜 구현시
protocol Cafe {
func coffee()
func dessert()
}
// 공통된 기능을 줄 수있다.
class CafeOne: Cafe {
func coffee() {
print("아메리카노와 라떼가 있습니다.")
}
func dessert() {
print("케이크와 마카롱이 있습니다.")
}
}
class CafeTwo: Cafe {
func coffee() {
print("아메리카노와 라떼, 바닐라 라떼가 있습니다.")
}
func dessert() {
print("휘낭시에와 르뱅쿠키가 있습니다.")
}
}
OOP | POP |
---|---|
객체 지향 | 프로토콜 지향 |
Subclassing을 통해 수직 구조로 타입을 확장 | Protocol을 통해 수평 구조로 타입 확장 |
단일 상속 | 프로토콜 구현으로 다중 상속처럼 사용 가능 |
Reference 타입만 구현 가능 | Extension을 통해 Reference/Value 타입 모두 구현 가능 |
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)
}
extension Sendable {
var from: Sendable { return self }
func send(data: Any) {
guard let reciver: Receiveable = self.to else { return }
reciver.received(data: data, from: self.from)
}
}
// 수신, 발신 모두 가능한 메일
class Mail: Receiveable, Sendable {
var to: Receiveable?
}
let myMail = Mail()
let yourMail = Mail()
myMail.to = yourMail
myMail.send(data: "안녕!") // myMail 이 yourMail 에게 "안녕!" 이라는 메세지 전송
참고문서
1. 객체지향의 사실과 오해 (일명 토끼책)와 야곰 책
2. Eddy의 벨로그
3. 프로토콜 참고 문서