일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
29 | 30 | 31 |
- error해결
- actionSheet
- 주간 달력
- Git
- avaliable
- 내_삶
- 파스칼표기법
- copy-on-write
- 글또
- unrecognized selector sent to class
- MyLife
- weekly calendar
- On branch is up to date with ' '
- 다짐글
- ios 개발 강의
- SWIFT
- struct
- 코드스니펫
- uikit
- Switch
- 바이트디그리
- class
- 생명주기
- 글또9기
- IOS
- 제어전송문
- 회고
- AnyObject
- 연관값
- K디지털기초역량훈련
- Today
- Total
seong_hye, the developer
Swift) 문법 정리 - 프로토콜 본문
프로토콜
규약 / 협약
최소한의 요구사항만 가지면 사용 가능
특정 역할을 하기 위한 메소드, 프로퍼티, 기타 요구사항등의 청사진
protocol MyProtocol {
func doing() -> Int // 요구사항
}
프로토콜이 필요한 이유?
상속의 경우 하나의 클래스만 상속이 가능( 다중 상속 불가능)
상속의 경우 기본적인 상위클래스의 메모리 구조를 따라갈 수 밖에 없음
(필요없는 속성/메서드도 상속됨)
class Bird {
var isFemale = true
func layEgg() {
if isFemale {
print("새가 알을 낳는다.")
}
}
func fly() {
print("새가 하늘로 날아간다.")
}
}
class Eagle: Bird {
// isFamale
// layEgg()
// fly()
func soar() {
print("공중으로 치솟아 난다.")
}
}
class Penguin: Bird {
// isFamale
// layEgg()
// fly() // 상속 구조에서는 펭귄이 어쩔 수 없이 날개됨 ⭐️
func swim() {
print("헤엄친다.")
}
}
// struct가 될 수도 없고(클래스로만 구현가능), 무조건 Bird를 상속해야만 함
class Airplane: Bird {
// isFamale
// layEgg() // 상속 구조에서는 비행기가 알을 낳게됨 ⭐️
override func fly() {
print("비행기가 엔진을 사용해서 날아간다")
}
}
프로토콜이 클래스의 단점을 보완함
// "fly()"라는 기능을 따로 분리해 내기
protocol CanFly {
func fly() // 구체적인 구현은 하지 않음 ===> 구체적인 구현은 자격증을 채택한 곳에서
}
class Bird1 {
var isFemale = true
func layEgg() {
if isFemale {
print("새가 알을 낳는다.")
}
}
}
class Eagle1: Bird1, CanFly { // "CanFly" 자격증을 채택
// isFemale
// layEgg()
func fly() {
print("독수리가 하늘로 날라올라 간다.")
}
func soar() {
print("공중으로 활공한다.")
}
}
class Penguin1: Bird1 {
// isFemale
// layEgg()
func swim() {
print("물 속을 헤엄칠 수 있다.")
}
}
// 구조체에서 채택도 가능
struct Airplane1: CanFly {
func fly() {
print("비행기가 날아간다")
}
}
프로토콜은 여러개의 프로토콜을 채택할 수 있음
클래스에서 상속이 있는 경우 상위 클래스를 먼저 선언 후 그 뒤에 프로토콜을 채택 선언함
class Student: Person, AProtocol, BProtocol {
// AProtocol, BProtocol이 원하는 내용 구현해야함
}
프로토콜 속성의 요구사항
인스턴스 속성 요구사항
최소한의 요구사항을 지정
속성의 뜻에서 let, var로 선언 (set 키워드 사용시 let으로 선언할 수 없음)
get, set 키워드를 통해서 읽기/쓰기 여부를 설정 (최소한의 요구사항일뿐)
저장 속성/계산 속성으로 모두 구현 가능
protocol RemoteMouse {
var id: String { get } // ===> let 저장속성 / var 저장속성 / 읽기계산속성 / 읽기,쓰기 계산속성
var name: String { get set } // ===> var 저장속성 / 읽기,쓰기 계산속성
static var type: String { get set } // ===> 타입 저장 속성 (static)
// ===> 타입 계산 속성 (class)
}
struct TV: RemoteMouse {
var id: String = "456"
var name: String = "삼성티비"
static var type: String = "리모콘"
}
타입 속성 요구사항
최소한의 요구사항을 지정
저장 타입 속성/계산 타입 속성으로 모두 구현 가능
채택 시 저장 타입 속성에서 static키워드로만 구현 가능 (저장 속성 재정의 불가 원칙)
클래스에서 채택시에만 계산 타입 속성에서 static / class 키워드로 모두 구현 가능
// 1) 저장 타입 속성으로 구현
class SmartPhone: RemoteMouse {
var id: String {
return "777"
}
var name: String {
get { "아이폰" }
set { }
}
static var type: String = "리모콘" // 타입 저장 속성은 (상속은 되지만) 재정의 원칙적 불가능
}
// 2) 계산 타입 속성으로 구현
class Ipad: RemoteMouse {
var id: String = "777"
var name: String = "아이패드"
class var type: String { // 타입 계산 속성은 재정의 가능 (class키워드 가능)
get { "리모콘" }
set { }
}
}
프로토콜 메서드 요구사항
메서드의 헤드부분(인풋/아웃풋)의 형태만 요구사항으로 정의
mutating 키워드: 구조체에서 저장 속성 변경하는 경우,
구조체도 채택 가능하도록 허락하는 키워드
타입 메서드로 제한 하려면, static키워드만 붙이면 됨
(채택해서 구현하는 쪽에서 static / class 키워드 모두 사용 가능)
// 1) 정의
protocol RandomNumber {
static func reset() // 최소한 타입 메서드가 되야함 (class로 구현해서 재정의를 허용하는 것도 가능)
func random() -> Int
//mutating func doSomething()
}
// 2) 채택 / 3) 구현
class Number: RandomNumber {
static func reset() {
print("다시 셋팅")
}
func random() -> Int {
return Int.random(in: 1...100)
}
}
관습적으로 프로토콜의 채택은 확장(Extension)에서 구현하는 것을 권장함
// 관습적으로 본체보다는 확장에서, 채택 구현 (코드의 깔끔한 정리 가능)
extension Person: Certificate {
func doSomething() {
print("Do something")
}
}
프로토콜의 확장
프로토콜을 채택한 모든 타입에서, 실제 구현을 계속적으로 반복해야하는 불편함을 덜기 위해
메서드의 디폴트 구현을 제공함 (코드의 중복을 피할 수 있음)
protocol Remote {
func turnOn()
func turnOff()
}
extension Remote {
func turnOn() { print("리모콘 켜기") }
func turnOff() { print("리모콘 끄기") }
func doAnotherAction() {
print("리모콘 또 다른 동작")
}
}
프로토콜 확장의 적용 제한
프로토콜 확장에서 where절을 통해, 프로토콜의 확장의 적용을 제한 가능
"특정 프로토콜"을 채택한 타입에만 프로토콜 확장이 적용되도록 제한
ex) where Self: 특정프로토콜
특정 프로토콜을 채택하지 않으면, 프로토콜의 확장이 적용되지 않기 때문에
확장이 없는 것과 동일하게 메서드를 직접구현 해야함
extension Bluetooth where Self: Remote {
func blueOn() { print("블루투스 켜기") }
func blueOff() { print("블루투스 끄기") }
}
class SmartPhone: Remote, Bluetooth {
}
참고자료)
https://www.udemy.com/course/ios-13-app-development-bootcamp/
'IOS' 카테고리의 다른 글
[ios 개발 강의] Swift - 에러 처리 (0) | 2022.07.12 |
---|---|
Swift) 문법 정리 - 열거형(Enum) (0) | 2022.07.12 |
Swift) 문법 정리 - 튜플 (0) | 2022.07.12 |
Swift) 문법 정리 - 타입 캐스팅(Type Casting) / Any, AnyObject (0) | 2022.07.12 |
Swift) 문법 정리 - 상속 (0) | 2022.07.12 |