跳到主要内容

Protocol-Oriented Programming

Introduction to Protocol-Oriented Programming

Core Concepts

protocol Identifiable {
var id: String { get }
func identify()
}

extension Identifiable {
func identify() {
print("My ID is \(id)")
}
}

struct User: Identifiable {
let id: String
}

Protocol Composition

Combining Protocols

protocol Named {
var name: String { get }
}

protocol Aged {
var age: Int { get }
}

typealias Person = Named & Aged

struct Employee: Person {
let name: String
let age: Int
}

Protocol Extensions

Default Implementations

protocol Drawable {
func draw()
var size: CGSize { get }
}

extension Drawable {
func draw() {
print("Drawing with size: \(size)")
}

func scale(by factor: CGFloat) -> CGSize {
return CGSize(width: size.width * factor,
height: size.height * factor)
}
}

Type Constraints

Associated Types

protocol Collection {
associatedtype Element
var items: [Element] { get set }
mutating func add(_ item: Element)
}

struct Stack<T>: Collection {
typealias Element = T
var items: [T] = []

mutating func add(_ item: T) {
items.append(item)
}
}

Best Practices

1. Protocol Inheritance

protocol Animal {
var species: String { get }
}

protocol Pet: Animal {
var name: String { get }
var owner: String { get }
}

struct Dog: Pet {
let species: String = "Canis lupus familiaris"
let name: String
let owner: String
}

2. Protocol Witnesses

protocol DataProvider {
func fetchData() async throws -> Data
}

struct NetworkDataProvider: DataProvider {
let url: URL

func fetchData() async throws -> Data {
let (data, _) = try await URLSession.shared.data(from: url)
return data
}
}

Common Patterns

1. Dependency Injection

protocol APIClient {
func fetch<T: Decodable>(_ type: T.Type, from endpoint: String) async throws -> T
}

class UserService {
private let apiClient: APIClient

init(apiClient: APIClient) {
self.apiClient = apiClient
}

func fetchUser(id: String) async throws -> User {
return try await apiClient.fetch(User.self, from: "/users/\(id)")
}
}

2. Protocol-Based Validation

protocol Validatable {
func validate() throws
}

struct ValidationError: Error {
let message: String
}

struct UserCredentials: Validatable {
let username: String
let password: String

func validate() throws {
guard username.count >= 4 else {
throw ValidationError(message: "Username too short")
}
guard password.count >= 8 else {
throw ValidationError(message: "Password too short")
}
}
}

Next Steps

  1. Study Testing and Debugging
  2. Review Memory Management