Swift Language Nozioni di base sul protocollo


Esempio

Informazioni sui protocolli

Un protocollo specifica inizializzatori, proprietà, funzioni, pedici e tipi associati richiesti di un tipo di oggetto Swift (classe, struct o enum) conforme al protocollo. In alcune lingue idee simili per le specifiche dei requisiti degli oggetti successivi sono conosciute come "interfacce".

Un Protocollo dichiarato e definito è un Tipo, in sé e per sé, con una firma dei suoi requisiti dichiarati, in qualche modo simile al modo in cui le Funzioni Swift sono un Tipo basato sulla loro firma di parametri e ritorni.

Le specifiche del protocollo Swift possono essere facoltative, richieste esplicitamente e / o fornite implementazioni predefinite tramite una funzione nota come Extension Protocol. Un tipo di oggetto Swift (classe, struct o enum) che desidera conformarsi a un protocollo che è arricchito con estensioni per tutti i suoi requisiti specificati, deve solo indicare il suo desiderio di conformarsi per essere in piena conformità. La funzionalità di implementazione predefinita delle estensioni del protocollo può essere sufficiente per soddisfare tutti gli obblighi di conformità a un protocollo.

I protocolli possono essere ereditati da altri protocolli. Questo, in congiunzione con Protocol Extensions, significa che i protocolli possono e devono essere considerati come una caratteristica significativa di Swift.

I protocolli e le estensioni sono importanti per realizzare gli obiettivi e gli approcci più ampi di Swift alla flessibilità della progettazione del programma e ai processi di sviluppo. Lo scopo principale dichiarato della capacità di protocollo e estensione di Swift è l'agevolazione della progettazione compositiva nell'architettura e nello sviluppo del programma. Si parla di programmazione orientata al protocollo. I vecchi croccanti considerano questo superiore l'attenzione al design OOP.

I protocolli definiscono interfacce che possono essere implementate da qualsiasi struct , classe o enum :

protocol MyProtocol {
    init(value: Int)                      // required initializer
    func doSomething() -> Bool            // instance method
    var message: String { get }           // instance read-only property
    var value: Int { get set }            // read-write instance property
    subscript(index: Int) -> Int { get }  // instance subscript
    static func instructions() -> String  // static method
    static var max: Int { get }           // static read-only property
    static var total: Int { get set }     // read-write static property
}

Le proprietà definite nei protocolli devono essere annotate come { get } o { get set } . { get } significa che la proprietà deve essere disponibile e quindi può essere implementata come qualsiasi tipo di proprietà. { get set } significa che la proprietà deve essere impostabile e ricevibile.

Una struttura, una classe o una enum possono essere conformi a un protocollo:

struct MyStruct : MyProtocol {
    // Implement the protocol's requirements here
}
class MyClass : MyProtocol {
    // Implement the protocol's requirements here
}
enum MyEnum : MyProtocol {
    case caseA, caseB, caseC
    // Implement the protocol's requirements here
}

Un protocollo può anche definire un'implementazione predefinita per uno qualsiasi dei suoi requisiti attraverso un'estensione :

extension MyProtocol {
    
    // default implementation of doSomething() -> Bool
    // conforming types will use this implementation if they don't define their own
    func doSomething() -> Bool {
        print("do something!")
        return true
    }
}

Un protocollo può essere usato come un tipo , a condizione che non abbia i requisiti del tipo associatedtype :

func doStuff(object: MyProtocol) {
    // All of MyProtocol's requirements are available on the object
    print(object.message)
    print(object.doSomething())
}

let items : [MyProtocol] = [MyStruct(), MyClass(), MyEnum.caseA]

Puoi anche definire un tipo astratto conforme a più protocolli:

3.0

Con Swift 3 o superiore, questo viene fatto separando la lista dei protocolli con una e commerciale ( & ):

func doStuff(object: MyProtocol & AnotherProtocol) {
    // ...
}

let items : [MyProtocol & AnotherProtocol] = [MyStruct(), MyClass(), MyEnum.caseA]
3.0

Le versioni precedenti hanno il protocol<...> sintassi protocol<...> dove i protocolli sono un elenco separato da virgole tra parentesi angolari <> .

protocol AnotherProtocol {
    func doSomethingElse()
}

func doStuff(object: protocol<MyProtocol, AnotherProtocol>) {
    
    // All of MyProtocol & AnotherProtocol's requirements are available on the object
    print(object.message)
    object.doSomethingElse()
}

// MyStruct, MyClass & MyEnum must now conform to both MyProtocol & AnotherProtocol
let items : [protocol<MyProtocol, AnotherProtocol>] = [MyStruct(), MyClass(), MyEnum.caseA]

I tipi esistenti possono essere estesi per conformarsi a un protocollo:

extension String : MyProtocol {
    // Implement any requirements which String doesn't already satisfy
}