2017-05-09 1 views
1

ich folgenden Code haben:Swift - wie eine Art Zwang zu definieren, die die Art garantieren eine init hat

struct MyStruct { 
    var v: Int = 1 
} 

func createInstance<T: Any>(type: T.Type) -> T 
{ 
    return type.init() 
} 

let myType = MyStruct.self 
let instance = createInstance(type: myType) 

Das funktioniert nicht, weil ich nicht garantieren, hat die T eine init.

Playground execution failed: error: MyPlayground.playground:76:12: error: type 'T' has no member 'init' 
return type.init() 
     ^~~~ ~~~~ 

Aber wie kann ich eine Einschränkung definieren, die die Art eines init hat garantiert?

+0

Können Sie ein 'Initializable'-Protokoll haben, das diese Strukturen und Klassen implementieren müssen? – NRitH

+0

Meinst du nur ein leeres Protokoll das sie implementieren müssen? Hm ein bisschen seltsam, aber es klingt wie ein netter Trick :) Ich werde es versuchen. – Dareon

+0

Was genau versuchen Sie mit 'createInstance (type))' zu erreichen? Es gibt einen Grund dafür, dass es in der Standardbibliothek kein 'DefaultConstructible' (oder ähnliches) Protokoll gibt - ohne begleitende Semantik ist * nur * initialisierbar, ist das nicht sinnvoll. Ich würde empfehlen zu lesen [Protokolle sind mehr als Taschen der Syntax] (https://oleb.net/blog/2016/12/protocols-haves-semantics/). – Hamish

Antwort

2

Sie könnte ein eigenes Protokoll erstellen, die die init() Methode Items herzustellen, und verwenden Sie dieses Protokoll als eine Art Zwang für den generischen Typenhalter in Ihrer createInstance Funktion. Z.B .:

protocol SimplyInitializable { 
    init() 
} 

struct MyStruct: SimplyInitializable { 
    var v: Int = 1 
} 

func createInstance<T: SimplyInitializable>(type: T.Type) -> T 
{ 
    return type.init() 
} 

let myType = MyStruct.self 
let instance = createInstance(type: myType) 

Art, die (ausdrücklich) oben SimplyInitializable entspricht in der Lage, die Verwendung der createInstance Methode (beachten Sie die Konformität von MyStruct-SimplyInitializable) zu machen.


Als Alternative zu dem Ansatz oben, Sie ebenfalls könnten, wenn Sie möchten, dass die Verwendung eines generischen struct eher machen als eine globale generische createInstance Methode Instanzen von Typen zu erstellen, die SimplyInitializable entsprechen. Beispiel:

protocol SimplyInitializable { 
    init() 
} 

struct SimpleFactory<T: SimplyInitializable> { 
    static func createInstance() -> T { 
     return T.init() 
    } 
} 

struct MyStruct: SimplyInitializable { 
    var v: Int = 1 
} 

let instance = SimpleFactory<MyStruct>.createInstance() 
+0

Perfekt, habe ich falsch Protokoll mit Func init() versucht. Vielen Dank. – Dareon

+0

@Dareon gerne helfen. Sehen Sie sich auch den sehr verwandten und relevanten Blog-Eintrag von Hamish in einem Kommentar zu Ihrer Frage an. Die obige Antwort zeigt, dass Sie technisch gesehen die gewünschte Funktionalität erreichen können, während der Blogbeitrag erläutert, warum Protokolle wie "SimplyInitializable" oben einen sehr schlechten semantischen Wert haben und es eine schlechte Idee wäre, z. in den Stdlibs von Swift. – dfri

Verwandte Themen