Menu
Coddy logo textTech

Protokol Uzantıları

Coddy'nin Swift Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 29 / 57.

Bir protokol uzantısı, bir protokolün metotlarına varsayılan bir uygulama sağlar. Protokole uyan her tür bunu ücretsiz olarak alır ve bir tür yine de kendi sürümünü sağlayabilir:

protocol Greeter {
    var name: String { get }
    func greet() -> String
}

extension Greeter {
    func greet() -> String { "Hello, \(name)!" }
}

struct English: Greeter { let name: String }
struct Pirate: Greeter {
    let name: String
    func greet() -> String { "Ahoy, \(name)!" }
}

print(English(name: "Ada").greet())
print(Pirate(name: "Ada").greet())

Çıktı:

Hello, Ada!
Ahoy, Ada!

Bir uzantı, yalnızca gereksinimlerden oluşturulan yeni yöntemler de ekleyebilir. Uygunluk sağlayan bir tür, gereken küçük kısmı yazar ve geri kalanını alır:

protocol Scored {
    var points: [Int] { get }
}

extension Scored {
    var total: Int { points.reduce(0, +) }
    var best: Int { points.max() ?? 0 }
    func summary() -> String { "total \(total), best \(best)" }
}

struct Player: Scored {
    let points: [Int]
}

print(Player(points: [3, 9, 4]).summary())

Çıktı:

total 16, best 9

Bu, kalıtım olmadan yapılar, sınıflar ve enum'lar arasında davranış paylaşır. Standart kütüphane de aynı şekilde çalışır: her Collection, isEmpty, first ve map özelliklerini protokol uzantılarından alır.

extension Collection {
    // isEmpty, first, map, filter, ... hepsi burada bir kez tanımlanır
    // ve her array, set, dictionary ve string bunları alır
}

Kısıtlanmış bir uzantı, yalnızca where ile yazılan bazı uyumlu türler için yöntemler ekler:

protocol Container {
    associatedtype Item
    var items: [Item] { get }
}

extension Container where Item == Int {
    var sum: Int { items.reduce(0, +) }
}

struct Box: Container {
    var items: [Int]
}

print(Box(items: [2, 5]).sum)

Çıktı:

7
challenge icon

Görev

Kolay

Priced adlı bir protokol tanımlayın; bu protokol var price: Int { get } (sent cinsinden) ve var formatted: String { get } gerektirmelidir. Bir protokol uzantısında, formatted için $4.50 döndüren bir varsayılan tanımlayın ve fiyatın bütçeye uyup uymadığını döndüren isAffordable(budget:) metodunu ekleyin. Coffee (fiyatı 450) ve Sandwich (saklanan bir price) yapılarını bu protokole uygun hâle getirin. Coffee, varsayılan formatted değerini coffee $4.50 ile değiştirmelidir.

Sağlanan kod bir bütçe ve ardından coffee veya sandwich,650 satırlarını okur. Her öğe için formatted değerini ve yes ya da no yazdırır.

Kodunuz Priced.swift, Coffee.swift ve Sandwich.swift dosyalarına yazılmalıdır. main.swift sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

// Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
var input: [String] = []
while let line = readLine() { input.append(line) }
let budget = Int(input[0])!
for line in input.dropFirst() {
    let item: any Priced = line == "coffee" ? Coffee() : Sandwich(price: Int(line.split(separator: ",")[1])!)
    print("\(item.formatted) \(item.isAffordable(budget: budget) ? "yes" : "no")")
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Swift playground