프로토콜(Protocols)
- 프로토콜(Protocol)은 영어로 규약(Agreement) / 협약(Convention) 을 의미한다
- 프로토콜은 특정 능력이나 기능을 정의하는 일종의 자격증 이라고 볼 수 있다
- 프로토콜을 통해 구조체, 클래스, 열거형 등이 특정 기능을 반드시 구현하도록 강제할 수 있다
- 프로토콜은 클래스 상속의 단점을 보완하는 중요한 개념 이다
프로토콜의 정의 및 구현
정의
protocol Instrument {
func play()
}
Instrument 프로토콜은 play() 라는 메서드를 요구한다
- 구체적인 구현은 프로토콜을 채택한 타입에서 수행하게 된다
프로토콜의 채택 및 구현
struct Drum: Instrument {
func play() {
print("드럼을 연주합니다.")
}
}
class Violin: Instrument {
func play() {
print("바이올린을 연주합니다.")
}
}
Drum 과 Violin 은 Instrument 프로토콜을 채택하여 play() 기능을 구현한다
- 프로토콜을 채택하면, 정의된 요구사항을 반드시 구현해야 한다
클래스 상속의 단점과 문제점 예시
class Animal {
var isFemale = true
func reproduce() {
if isFemale {
print("동물이 새끼를 낳습니다.")
}
}
func walk() {
print("동물이 걷습니다.")
}
}
class Dog: Animal {
func bark() {
print("개가 짖습니다.")
}
}
class Fish: Animal {
func swim() {
print("물고기가 헤엄칩니다.")
}
}
class Robot: Animal {
override func walk() {
print("로봇이 기계적으로 걷습니다.")
}
}
Fish 는 walk() 메서드를 상속받지만, 물고기는 걷지 않으므로 문제가 발생한다
Robot 은 동물이 아님에도 Animal 클래스를 상속받아야 하므로 설계가 비효율적이다
- 불필요한 메서드와 속성을 강제로 상속받게 되는 문제 가 발생한다
문제점 해결을 위한 프로토콜 사용
protocol Movable {
func move()
}
Movable 프로토콜은 이동 능력을 정의한다
- 클래스, 구조체, 열거형 등에서 구현할 수 있다
클래스에서 프로토콜 채택
class Dog1: Animal, Movable {
func move() {
print("개가 뛰어다닙니다.")
}
}
class Fish1: Animal, Movable {
func move() {
print("물고기가 헤엄칩니다.")
}
}
Dog1 과 Fish1 클래스는 Movable 프로토콜을 채택하여 move() 기능을 구현한다
- 기존의
Animal 클래스를 상속받으면서도 새로운 기능을 추가한다
구조체에서 프로토콜 채택
struct Car: Movable {
func move() {
print("자동차가 도로를 달립니다.")
}
}
Car 는 구조체로 정의되었지만, Movable 프로토콜을 채택하여 move() 기능을 구현할 수 있다
- 기존의 클래스 상속 방식에서는 불가능했던 방식이다
프로토콜을 사용하는 함수 정의
struct MovementDemo {
func demonstrateMovement(movingObject: Movable) {
movingObject.move()
}
}
demonstrateMovement() 함수는 Movable 프로토콜을 채택한 타입만 받을 수 있다
- 이 방식으로 특정 기능이 필요한 객체들만을 다룰 수 있게 된다
사용 예제
let myDog = Dog1()
let myFish = Fish1()
let myCar = Car()
myDog.reproduce()
myDog.move()
myFish.reproduce()
myFish.move()
myCar.move()
let demo = MovementDemo()
demo.demonstrateMovement(movingObject: myDog)
demo.demonstrateMovement(movingObject: myFish)
demo.demonstrateMovement(movingObject: myCar)
프로토콜 사용의 장점
- 다중 상속의 효과 제공 (Swift는 클래스의 다중 상속을 지원하지 않음)
- 불필요한 속성과 메서드의 상속 문제 해결
- 클래스(참조 타입) 뿐 아니라, 구조체(값 타입), 열거형도 프로토콜을 채택할 수 있음
- 타입 안전성을 강화하여 특정 기능이 필요한 타입만을 사용할 수 있게 함
요약
- 프로토콜은 클래스 상속의 문제를 해결하기 위해 사용되는 기능이다
- 프로토콜은 클래스뿐 아니라 구조체, 열거형에도 적용할 수 있다
- 프로토콜은 특정 기능을 강제하여 타입 안전성을 보장한다
- 클래스 상속으로 인해 발생할 수 있는 비합리적인 상속 문제를 방지할 수 있다