📚 프로토콜 (Protocol)
- 프로토콜 자체는 기능을 구현하지 않으며, 오직 설계만 제공합니다.
- class, struct, enum에서 프로토콜을 채택할 수 있으며, 프로토콜에서 정의한 프로퍼티와 메소드를 모두 구현해야 합니다.
- 프로토콜을 채택하는 방법은 타입의 이름 뒤에 : 콜론을 넣은 후 프로토콜 이름을 작성하면 됩니다.
- 프로토콜은 여러 개를 채택 할 수 있으며, 프로토콜 이름을 , 로 구분합니다.
- 프로토콜에서 정의된 프로퍼티는 항상 var로 선언되어야 합니다.
- 프로토콜에서 정의하는 프로퍼티는 읽기 전용 { get } 또는 읽기-쓰기 가능 { get set }으로 설정할 수 있습니다.
- { get }으로만 설정해도 프로퍼티의 값을 변경할 수 있지만, 명시적으로 작성하면 코드의 의도를 쉽게 파악할 수 있습니다.
- 프로토콜에서 정의하는 메소드는 이름, 파라미터, 리턴타입만 선언하며, 구현부 { }는 작성하지 않습니다.
- Swift에서 프로토콜은 다른 언어에서 말하는 인터페이스 개념과 유사합니다.
프로토콜 정의 방법
1️⃣ 기본 정의 방법
protocol 프로토콜이름 {
// 프로퍼티 정의
// 메소드 정의
}
protocol FullyNamed {
var fullName: String { get }
func sayMyFullName() -> String // 구현부는 작성하지 않습니다.
}
2️⃣ 프로토콜 채택하여 구현하는 방법
// 1개의 프로토콜 채택
protocol FullyNamed {
var fullName: String { get }
func sayMyFullName() -> String // 구현부는 작성하지 않습니다.
}
class Person: FullyNamed { // FullyName 프로토콜을 채택합니다.
var fullName: String // FullyName 프로토콜에 있는 fullName 프로퍼티를 구현해야 합니다.
func sayMyFullName() -> String { // 프로토콜에 있는 메소드를 구현해야 합니다.
return fullName
}
init(fullName: String) {
self.fullName = fullName
}
}
var person = Person(fullName: "Brody")
print(person.fullName) // "Brody" 출력
print(person.sayMyFullName()) // "Brody" 출력
3️⃣ 여러개의 프로토콜 채택 하는 방법
// 여러개의 프로토콜 채택
protocol FullyNamed {
var fullName: String { get }
func sayMyFullName() -> String
}
protocol ShortNamed {
var shortName: String { get }
}
class Person: FullyNamed, ShortNamed { // 프로토콜 여러개를 채택하는 클래스입니다.
var fullName: String
func sayMyFullName() -> String {
return fullName
}
var shortName: String {
return "ShortName"
}
init(fullName: String) {
self.fullName = fullName
}
}
var person = Person(fullName: "Brody")
print(person.fullName) // "Brody" 출력
print(person.sayMyFullName()) // "Brody" 출력
print(person.shortName) // "ShortName" 출력
4️⃣ 클래스 전용 프로토콜 만들기
- class 전용 프로토콜은 struct, enum에서 사용될 수 없습니다.
- 프로토콜 정의 시, AnyObject를 채택하면 클래스 전용 프로토콜로 만들 수 있습니다.
protocol OnlyClassProtocol: AnyObject {
}
실습하기
import UIKit
// 프로토콜 실습하기
protocol Walkable {
var feetCount: Int {set get}
func walk() -> String
}
protocol Introduceable {
func introduce()
}
class Person: Walkable, Introduceable {
var feetCount: Int = 2
var name: String
func walk() -> String {
return "사람이 걷습니다"
}
init(name: String) {
self.name = name
}
func introduce() {
print("이름은 \(name) 입니다. 발 갯수는 \(feetCount)개 입니다.")
}
}
struct Cat: Walkable, Introduceable {
var feetCount: Int = 4
var color: String
func walk() -> String {
return "고양이가 걷습니다."
}
init(color: String) {
self.color = color
}
func introduce() {
print("고양이 털 색은 \(color)이고, 발 갯수는 \(feetCount)개 입니다.")
}
}
let person = Person(name: "Brody")
person.introduce()
print(person.walk())
let cat = Cat(color: "노란색")
cat.introduce()
print(cat.walk())
📚 확장 (Extension)
- extension 키워드를 사용하여 기존 타입을 확장할 수 있습니다.
- 하나 이상의 프로토콜을 extension으로 추가해 적용할 수 있습니다. 이를 통해 기존 타입을 수정하지 않고 프로토콜 요구사항을 구현할 수 있어 코드 유지보수가 편리해집니다.
- 하나의 타입에 extension 여러 번 가능합니다.
- 확장할 수 있는 것들은 아래와 같습니다.
- 연산 프로퍼티
- 확장된 곳에서 저장 프로퍼티는 사용할 수 없습니다.
- 메소드
- 새로운 초기화 init
- 중첩된 타입(Nested Type)
- 연산 프로퍼티
프로토콜 사용 방법
1️⃣ 기본 사용 방법
// 기본 사용 방법
struct Person {
let name: String
}
// extension 키워드 작성 후 확장시키고 싶은 타입 이름을 명시합니다.
extension Person {
}
// 특정 타입의 프로토콜을 확장시키고 싶을 때
extension Person: Equatable {
}
2️⃣ 확장할 수 있는 것들
// 확장할 수 있는 것들
struct Person {
let lastName: String
let firstName: String
let age: Int
}
protocol FullyNamed {
var fullName: String { get }
func sayMyFullName() -> String
}
// extension에서 연산 프로퍼티를 구현할 수 있습니다.
extension Person {
var nameAge: String {
return "\(firstName)(\(age)세)"
}
}
// extension에서 메소드를 구현할 수 있습니다.
extension Person {
func sayHello() {
print("\(firstName)님 안녕하세요?")
}
}
// extension에서 protocol을 채택하여 구현할 수 있습니다.
extension Person: FullyNamed {
var fullName: String {
return "\(lastName)\(firstName)"
}
func sayMyFullName() -> String {
return "제 이름은 \(fullName)입니다."
}
}
let person = Person(lastName: "홍", firstName: "길동", age: 20)
print(person.nameAge) // extension에서 구현한 연산프로퍼티를 사용할 수 있습니다.
person.sayHello() // extension에서 구현한 메소드를 호출할 수 있습니다.
print(person.fullName) // extension에서 구현한 프로토콜을 사용할 수 있습니다.
print(person.sayMyFullName()) // extension에서 구현한 프로토콜을 사용할 수 있습니다.
/* 출력 값
길동(20세)
길동님 안녕하세요?
홍길동
제 이름은 홍길동입니다.
*/
실습하기
import UIKit
// 프로토콜 실습하기
protocol Walkable {
var feetCount: Int {set get}
func walk() -> String
}
protocol Introduceable {
func introduce()
}
class Person: Introduceable {
var feetCount: Int = 2
var name: String
init(name: String) {
self.name = name
}
func introduce() {
print("이름은 \(name) 입니다. 발 갯수는 \(feetCount)개 입니다.")
}
}
extension Person {
var fullNameWithFeetCount: String {
return "\(name)_\(feetCount)"
}
func introduceOnlyName() {
print("안녕하세요. \(name)입니다.")
}
}
extension Person: Walkable {
func walk() -> String {
return "사람이 걷습니다"
}
}
let person = Person(name: "Brody")
person.introduce()
print(person.walk())
✓ TIL
Swift에서 프로토콜은 다른 언어에서 말하는 인터페이스 개념과 유사하다.
프로토콜 내부에서는 선언만 하며, 구현은 채택 후 클래스나 구조체, 열거형 등에서 프로퍼티와 메소드를 모두 구현한다.
프로퍼티는 읽기 전용 또는 읽기-쓰기 가능으로 설정할 수 있다.
- 읽기 전용 : { get }
- 읽기 - 쓰기 : { get set }
Swift에서 확장은 extension 키워드를 사용하여 기존 타입을 확장할 수 있다.
코드의 유지보수가 편리해진다.
'스파르타 코딩 클럽 - iOS 스타터 6기 > 본 캠프' 카테고리의 다른 글
19. 스파르타 코딩 클럽 - 야구 게임 만들기 Lv1 (2) | 2025.03.19 |
---|---|
18. 스파르타 코딩 클럽 - 메모리 구조 (1) | 2025.03.18 |
16. 스파르타 코딩 클럽 - 접근제어자 (0) | 2025.03.17 |
15. 스파르타 코딩 클럽 - 옵셔널 언래핑 (0) | 2025.03.17 |
14. 스파르타 코딩 클럽 - 옵셔널 (1) | 2025.03.17 |