2016-10-30 2 views
0

Ich versuche, einen Initializer für das Protokoll A auf einem Typ erforderlich, der sowohl A entspricht als auch eine Unterklasse von C ist.Generische Constraints und Initialisierung Vererbung in Swift

Alles ist gut und gut, wenn C eine Basisklasse ist. Aber sobald C Unterklassen eine andere Klasse, sagen wir B, bricht es.

Hier ist, was ich rede:

protocol A { 
    init(foo: String) 
} 

class B { 
    init() {} 
} 

class C: B {} 

func makeSomething<T: A>() -> T where T: B { 
    return T(foo: "Hi") 
} 

, das funktioniert. Aber wenn ich where T: B zu where T: C ändere, erhalte ich den folgenden Fehler: argument passed to call that takes no arguments. Es wird mir nur erlauben, B s init anzurufen.

Warum kann ich diesen Initialisierer nicht aufrufen? Ich verstehe, dass die Superklasse ihre eigenen Initiatoren hat, die aufgerufen werden müssen. Aber das wird erzwungen, wenn jemand tatsächlich die Klasse der Unterklasse B schreibt und A entspricht. (Z. B. Implementierung und Aufruf super.init(bar: Int) innen).

Jede Hilfe hier würde sehr geschätzt werden. Vielen Dank!

Antwort

0

Swift bietet einen Standard-Initialisierer für Ihre Basisklasse, wenn alle Eigenschaften initialisiert wurden, aber nicht im Falle von Generics, da Swift denkt, dass seine Eigenschaften nicht initialisiert wurden.

Also, wenn Sie Ihren Rückgabetyp als

func makeSomething<T: A>() -> T where T: C 

Zwang erfordert es Initialisierung für die Klasse C als Swift kann keinen Standard bieten initializer.But wenn Ihr Entfernen des where-Klausel funktioniert alles einwandfrei

func makeSomething<T: A>() -> T { 
    return T(foo:"string") 
} 

Wenn Sie zurückgeben möchten return T(foo: "Hi"):

Sie erhalten Fehler bec AVerwenden Klasse C haben initializer nicht die init(foo: String)

Ändern Sie Ihre Klasse C als

class C: A { 
    required init(foo: String) { 

    } 
} 

akzeptiert die, die das Argument Typ akzeptiert mindestens einen Initialisierer zur Verfügung stellt.

Also denken Sie daran, wenn Sie nicht Unterklasse Es gibt bereits einen Initialisierer Ihre Arbeit zu tun und Sie erhalten keinen Fehler.