Ich mag ein generisches Protokoll GBucket
definieren, die ein bisschen ist wie eine Reihe von Elementen des gleichen Typs. Ein bisschen wie ein CollectionType
, aber mit weit weniger Fähigkeiten. Wie so:
public protocol GBucket {
associatedtype BElement
func splitBucket
<A: GBucket, B: GBucket where A.BElement == Self.BElement,
B.BElement == Self.BElement>
(idx: Int) -> (A, B)
}
Es Wesentlichen bietet nur eine Methode ein GBucket
in zwei neue GBucket
s aufgeteilt. Das kann von jedem Typ sein, der mit dem Protokoll übereinstimmt - d. H. Die zurückgegebenen Teile müssen nicht die gleiche Klasse sein, die die Aufteilung durchführt.
Ich habe versucht, das als Beispielimplementierung:
extension ArraySlice : GBucket {
public typealias BElement = Generator.Element
public func splitBucket
<A: GBucket, B: GBucket where A.BElement == BElement,
B.BElement == BElement>
(idx: Int) -> (A, B)
{
let ls : ArraySlice<A.BElement> = self[0..<idx]
let a : A = ls // this conversion FAILs
return (a, self[idx..<self.count]) // this too, of course ;-)
}
}
Dies erzeugt:
Wert kann nicht vom Typ umwandeln 'ArraySlice < Element>' in dem angegebenen Typ 'A'
Was soweit ich sagen kann sollte sich gut konvertieren. ArraySlice
ist ein GBucket
und der Elementtyp ist der gleiche dank der where
Spezifikation.
Und eine andere, kürzere Probe das Problem darstellt, das nicht Array Sachen nicht verwendet:
public protocol GBucket {
associatedtype BElement
func otherBucket<A: GBucket where A.BElement == Self.BElement>() -> A
}
public class MyBucketType<T> : GBucket {
public typealias BElement = T
public func otherBucket<A: GBucket where A.BElement == BElement>() -> A {
return MyBucketType<A.BElement>()
}
}
Was mir falsch doin?
„Sie können von speziellere Typen gegossen allgemeinere Typen“ - soweit ich das sehe ich nicht. A * ist auf "BElement" durch die 'where'-Klausel auf genau denselben Typ spezialisiert - was genau meine Absicht ist. – hnh
Ihre Antwort fehlt meine Anforderung "die zurückgegebenen Teile müssen nicht die gleiche Klasse sein, die den Split macht". I.e. Dies soll gelten: 'extension _ArrayType: GBucket {func splitBucket() -> (ArraySlice, ArraySlice)'. Das heißt, die Split-Funktion kann jede Art von "GBucket" zurückgeben, solange sie dem Elementtyp entspricht. Mit Ihrem Ansatz konnte _ArrayType nur _ArrayType und nicht ArraySlices zurückgeben. – hnh
Ok, um Ihre splitBucket () -Funktion zu bekommen, um Objekte vom Typ A und B zurückzugeben, muss es eine Methode haben, um diese Objekte zu initialisieren, momentan gibt es keine Methode, dies zu ermöglichen. –