- 프로토콜이란? 오직 인터페이스만 있는 상태로 구현하는 부분없이 프로퍼티나 메소드를 선언한 형태로 정의된 API를 의미한다.
- 프로토콜 정의와 채택(사용)
- 프로토콜 정의프로토콜 정의
protocol PROTOCOL_NAME {
// 프로퍼티 선언
// 메소드 선언
} - 프로토콜 채택 : 클래스나 구조체에서 정의된 프로토콜을 이용하는 것을 프로토콜을 채택했다고 한다. 프로토콜 채택 시에는 프로토콜에 정의된 프로퍼티, 메소드는 반드시 클래스나 구조체에서 구현이 되어야 한다.프로토콜 채택
// 프로토콜 정의
protocol PROTOCOL_NAME {
// 프로퍼티 선언
// 메소드 선언
}
// 클래스에서 프로토콜 채택
class CLASS_NAME : PROTOCOL_NAME {
}
// 구조체에서 프로토콜 채택
struct STRUCT_NAME : PROTOCOL_NAME {
} - 클래스의 상속과 프로토콜 : 클래스에서는 부모 클래스를 상속하고, 프로토콜 채택을 모두 할 수 있으며 아래와 같이 정의한다.클래스 상속과 프로토콜
// 프로토콜 정의
protocol PROTOCOL_NAME {
// 프로퍼티 선언
// 메소드 선언
}
// 부모 클래스
class PARENT_CLASS {
}
// 자식 클래스에서 부모 클래스 상속과 프로토콜 채택
class CHILD_CLASS : PARENT_CLASS, PROTOCOL_NAME {
}
/* 부모 클래스를 먼저 쓰고, 그 다음에 콤마 다음에 프로토콜을 쓴다.*/ - 프로토콜 상속 : 프로토콜은 다중 상속이 가능하여 여러 프로토콜을 상속할 수 있다.프로토콜 정의
protocol Singing {
func sing() {}
}
protocol Dancing {
func dance() {}
}
// Singing, Dancing에 정의된 메소드를 모두 구현해야한다.
protocol Entertaining : Singing, Dancing {
}
// Entertaining 프로토콜 채택 시 상속된 모든 메소드를 구현
class Human : Entertaining {
func sing() {print("라라라")}
func dance() {print("둠칫둠칫")}
} - 프로토콜 내 프로퍼티 선언 : 프로퍼티의 타입 선언 가능하고, 구현 시에 저장 프로퍼티로 사용할지 계산 프로퍼티로 사용할지 프로토콜 채택 후에 정한다.프로퍼티 선언
protocol Singing {
// 프로퍼티 선언
var duration : Int {get set}
}
// 저장 프로퍼티로 구현
struct MyStruct : Singing {
var duration : Int
}
// 계산 프로퍼티로 구현
class MyClass : Singing {
var duration : Int {
get { return 0 }
set { }
}
} - 프로토콜 내 Initializer 선언 : 프로토콜 내에 Initializer 선언이 가능하고, 클래스에서 구현 시에는 required를 추가한다.프로토콜 내 Initializer 구현
protocol Singing {
var sing : String
// Initializer
init(sing : String)
}
// 클래스가 프로토콜을 채택 시 Initializer 구현
class Monster : Singing {
required init(sing : String) {
self.sing = sing
}
}
// 구조체가 프로토콜을 채택 시 Initializer 구현
struct Boss : Singing {
init(sing : String) {}
} - 프로토콜을 타입으로 사용 시 채택한 클래스나 구조체에 별도의 메소드가 구현되어 있어도, 프로토콜 내의 메소드, 프로퍼티만 사용 가능하다.프로토콜 내 Initializer 구현
protocol Singing {
// 메소드
func sing() {}
}
// 클래스가 채택하여 구현
class Human : Singing {
func sing() {
print("랄랄랄")
}
func dancing() {
print("쿵쿵쿵")
}
}
// 프로토콜을 타입으로 사용
var singingAnimal : Singing = Human()
singingAnimal.sing()
singingAnimal. dancing()// 사용 못함 - extension(확장)
- 기존에 작성된 타입(클래스나 구조체, enum)을 확장해서 사용할 수 있다.
- extension을 할 경우 하나의 타입으로 동작한다.extension 예시
class Dog{
func eat() {
print("뭐든 잘 먹어요.")
}
}
// 확장
extension Dog {
func sing() {
print("멍~멍~")
}
}
var myDog = Dog()
myDog.eat()
myDog.sing() // 확장한 메소드 사용 가능 - extension이 가능한 것과 불가능한 것
- 가능한 것
- convenience initializer
- 계산 프로퍼티
- 메소드
- 프로토콜
- 서브스크립트
- nested type
- 불가능한 것
- designated initializer
- 저장 프로퍼티
- 프로토콜과 프로토콜 extension
- 기존에 정의된 프로토콜을 확장하여 사용 가능하며, 프로토콜의 다중 상속을 이용하여 코드 중복을 없애는데 사용된다.
- 코드 중복이 발생되는 상황코드 중복 발생
class Bird{
func move() {
print("날아서 이동")
}
func sound() {
print("소리를 낸다.")
}
}
class Airplane{
func move() {
print("날아서 이동")
}
func sound() {
print("소리를 낸다.")
}
} - 코드 중복을 없애는데 프로토콜 확장을 사용프로토콜 확장으로 코드 중복 제거
protocol Movable() { }
extension Movable {
func move() {print("날아서 이동")}
}
protocol Soundable {}
extension Soundable {
func sound() {print("소리를 낸다.")}
}
// 중복되는 메소드를 프로토콜 확장으로 제거
class Bird : Movable, Soundable {
}
class Airplane : Movable, Soundable {
}