2017-01-05 1 views
0

ich ein Protokoll und zwei Klassen von denen esWie eine berechnete Eigenschaft einer generischen Klasse machen, hängen von der Klasse Zwängen

protocol A { } 
class B1 { } 
class B2: A { } 

nimmt ich eine berechnete Eigenschaft einer generischen Klasse haben möchte die hängt davon ab, ob der Typ A annimmt. Ich habe versucht, diese

class C<T> { 
    var v: Int { get { return 0 } } 
} 
extension C where T: A { 
    var v: Int { get { return 1 } } 
} 

Jetzt C<B1>().v return 0, aber C<B2>().v beschwert sich über mehrdeutige Verwendung von v. Wenn ich v in ein Verfahren verwandeln es funktioniert

class D<T> { 
    func v() -> Int { return 0 } 
} 
extension D where T: A { 
    func v() -> Int { return 1 } 
} 

Jetzt C<B1>().v() 0 zurück und C<B2>().v() gibt 1 zurück, wie beabsichtigt.

Warum unterscheidet sich der Getter-Ansatz vom Methodenansatz? Kann ich die berechnete Eigenschaft arbeiten lassen? Ich habe versucht,

class E<T> { 
    var v: Int { get { return get() } } 
    func get() -> Int { return 0 } 
} 
extension E where T: A { 
    func get() -> Int { return 1 } 
} 

aber jetzt E<B1>().v und E<B2>().v beide return 0, das heißt nur die unbeschränkte Implementierung von get verwendet wird. Kann ich den Compiler zwingen, die richtige Implementierung zu wählen?

Irgendwelche Gedanken? Für mich klingt das wie ein Fehler von Swift, aber ich weiß nicht genug um sicher zu sein. Ich verwende Swift 3 in XCode 8.2.1

UPDATE: Ich habe gerade bemerkt, dass selbst meine Methode Lösung nicht immer funktioniert und der Compiler manchmal entscheidet, mit der allgemeineren Implementierung egal was zu gehen. Ich bin nicht sicher, was das entscheidet (mein aktuelles Projekt ist größer und es ist ein bisschen schwierig, ein einfaches Beispiel zu finden) ... Also könnte ich ein allgemeineres Problem haben: Wie man eine Eigenschaft/Methode einer generischen Klasse zuverlässig macht verschiedene Dinge für verschiedene Einschränkungen seines Typs Argument (s) tun?

Antwort

1

Es könnte funktionieren, wenn Sie aktiv die Art der T in Ihrem berechneten Eigenschaft wie folgt überprüfen:

class D<T> { 
    var v: Int { 
     get { 
      if let _ = T.self as? A.Type { 
       return 1 
      } else { 
       return 0 
      } 
     } 
    } 
} 

let c = D<B2>() 
print (c.v) // the output is 1 

Oder noch kürzer:

var v: Int { return T.self is A.Type ? 1 : 0 } 
+0

Diese meine Fragen beantwortet, wie ich sie gefragt, und umfasst ein viele Fälle. Außer (und das ist, was ich wirklich brauchte :-)), wenn 'A'' ExpressibleByNilLiteral' ist und meine Implementierung ein 'nil' vom Typ' T' erzeugen muss, wenn 'T'' ExpressibleByNilLiteral' ist. Ich werde Ihre Antwort akzeptieren, da sie die Frage beantwortet, die ich gestellt habe, aber möchten Sie sich dazu äußern? – user3763801

+0

Nicht sicher, ich verstehe. Können Sie ein Beispiel geben, vielleicht in einer anderen Frage, um Klarheit zu schaffen? –

+0

Schauen Sie hier http://stackoverflow.com/questions/41492153/how-to-produce-a-nil-of-a-generic-type – user3763801

Verwandte Themen