2015-10-07 11 views
6

So che il titolo di questa interrogazione è confusa ma il comportamento bizzarro è spiegato nel seguente esempio:In Swift, perché metodo della sottoclasse non può ignorare l'uno, fornito da protocollo di estensione in superclasse

protocol Protocol { 
    func method() -> String 
} 

extension Protocol { 
    func method() -> String { 
     return "From Base" 
    } 
} 

class SuperClass: Protocol { 
} 

class SubClass: SuperClass { 
    func method() -> String { 
     return "From Class2" 
    } 
} 

let c1: Protocol = SuperClass() 
c1.method() // "From Base" 
let c2: Protocol = SubClass() 
c2.method() // "From Base" 

Come mai c1.method() e c2.method() restituiscono lo stesso? Come mai il method() in SubClass non funziona?

È interessante notare che, senza dichiarare il tipo di c2, questo sta andando a lavorare:

let c2 = SubClass() 
c2.method() // "From Class2" 
+0

bella domanda. Ne ho uno simile a http: // StackOverflow.it/questions/33702738/method-customization-in-sub-class-not-called;). Che è probabilmente un tuo duplicato. È come se il dispatch dinamico funzioni solo se la SuperClass implementa la funzione. – bm842

risposta

0

io non sono molto sicuro del meccanismo sottostante, ma deve essere qualcosa a che fare con il fatto che i protocolli don' t consentono necessariamente l'ereditarietà.

Un modo per risolvere questo problema è aggiungendo anche il metodo per SuperClass

import Foundation 
protocol Protocol: class { 
    func method() -> String 
} 

extension Protocol { 
    func method() -> String { 
     return "From Base" 
    } 
} 

class SuperClass: Protocol { 
    func method() -> String { 
     return "From Super" 
     } 
} 

class SubClass: SuperClass { 
    override func method() -> String { 
     return "From Class2" 
    } 
} 

let c1: Protocol = SuperClass() 
c1.method() // "From Super" 
let c2: Protocol = SubClass() 
c2.method() // "From Class2" 
+0

sì, è una soluzione alternativa. Ero solo curioso di sapere perché non funziona se non ci sono implementazioni in SuperClass – aquajach

0

Fondamentalmente sì, se v'è una superclasse conforme al protocollo, ma non fornisce un'implementazione per esso, la l'implementazione dell'estensione del protocollo sarà disponibile in sottoclassi, anche se le sottoclassi hanno un'implementazione (tuttavia devono essere castate alla superclasse o al tipo del protocollo).

Tuttavia, se la superclasse ha un'implementazione del metodo del protocollo, l'implementazione del protocollo non sarà disponibile né dalla superclasse né dalle sottoclassi.

+0

grazie per la risposta. Se SubClass non è una sottoclasse di SuperClass, ma semplicemente conforme a Protocol, come "class SubClass: Protocol {}". Quindi lasciare c2: Protocol = SubClass(), c2.method() // Da Class2, anche se I casi c2 come Protocollo. Quindi la mia conclusione attuale, oltre alla tua affermazione, è che "le sottoclassi non possono sovrascrivere i metodi di super-classe forniti dalle estensioni del protocollo". – aquajach

+0

@aquajach Buona osservazione, ho riscritto la mia risposta in base ad esso. –

1

Il problema è che c1 e c2 sono di tipo Protocol, come hai definito esplicitamente il loro tipo in questo modo (ricorda: i protocolli sono tipi completi). Ciò significa che quando chiama il numero method(), Swift chiama il numero Protocol.method.


Se si definisce qualcosa come:

let c3 = SuperClass() 

... c3 è di tipo SuperClass. Poiché SuperClass non ha una dichiarazione più specifica method(), è ancora utilizzato, Protocol.method(), quando si chiama c3.method().


Se si definisce qualcosa come:

let c4 = SubClass() 

... c4 è di tipo SubClass. Poiché SubClass ha una dichiarazione più specifica method(), viene utilizzato SubClass.method() quando si chiama c4.method().


Si potrebbe anche ottenere c2 chiamare SubClass.method(), da down-fusione a `SubClass:

(c2 as! SubClass).method() // returns "From Class2" 

Ecco una dimostrazione su SwiftStub.

+1

grazie per la risposta. Aggiungo SubClass2 (conforme al protocollo direttamente) e c5 su http://swiftstub.com/452669817/?v=beta. Vedete, una volta che c5 si conforma direttamente al Protocollo non tramite l'ereditarietà o la super classe, anche se lancio il c5 come Protocollo, continuerà a utilizzare l'implementazione del metodo di SubClass2, anziché quella predefinita dall'estensione del protocollo. Non è molto intuitivo per me. – aquajach

Problemi correlati