2016-06-14 12 views
0

Ich habe ein Problem mit der Kompilierung Tests Fälle in Swift. Es sieht so aus, als ob der Compiler Informationen über den Schablonentyp verliert, aber andere generische Methoden funktionieren gut. Was vermisse ich?Swift allgemeine Funktion kompiliert nicht im Test

public class MatchNorm { 

    public static func resolve1<T:SequenceType where T.Generator.Element:MatchNormElement>(list: T, lti: LinearTransformation, accuracy: Double) -> LinearTransformation { 
     // no problem 
     return MatchNorm.resolve1(list, lti: lti, accuracy: accuracy) 
    } 

    public static func resolve2<T:SequenceType where T.Generator.Element:MatchNormElement>(list: T, lti: LinearTransformation, accuracy: Double) -> LinearTransformation { 

     for elem in list { 
      print(elem.x) 
     } 
     return lti 
    } 
} 
public class MatchNormTest: XCTestCase { 
    func testMatchNorm1() { 
     var list = [MatchNormElement]() 

     // compilation error here! 
     let ll = MatchNorm.resolve1(list, lti: LinearTransformation(1), accuracy: 0.001) 
// MatchNormTest.swift:70:29: Cannot invoke 'resolve1' with an argument list of type '([MatchNormElement], lti: LinearTransformation, accuracy: Double)' 
// MatchNormTest.swift:70:29: Expected an argument list of type '(T, lti: LinearTransformation, accuracy: Double)' 
    } 
} 

aktualisieren

MatchNormElement ist ein Protokoll, also habe ich es konkreter. Jetzt funktioniert es.

func testMatchNorm1() { 
    var list = [Measurment]() 

     // works fine 
    let ll = MatchNorm.resolve1(list, lti: LinearTransformation(1), accuracy: 0.001) 
} 
+1

Ich ersetzte 'MatchNormElement' und' LinearTransformation' mit 'NSString' (und entfernte' resolve2', diese Methode wird nicht benötigt, um das Problem zu finden), und es gibt keine Kompilierungsfehler. Vielleicht wird diese Information Ihnen helfen. –

+0

Danke ShadowOf. MatchNormElement ist ein Protokoll. Und es sieht so aus, als müsste die Liste aus konkreten Typen bestehen. –

Antwort

1

Dies ist für den Compiler sinnvoll. Swift ermöglicht die Typkonvertierung für einen Concrete-Typ in eine protokollbasierte Variablenzuweisung.

Swift erlaubt jedoch nicht das Konvertieren einer Gruppe von Betonarten in eine Menge/ein Array von Protokoll, indem jedes davon konvertiert wird. Dies ist sinnvoll, weil der folgenden Gründe:

Lassen angenommen, wir haben diese an Ort und Stelle konstruiert:

protocol IntType {} 
extension Int: IntType{} 

Jetzt tun lässt die offensichtliche Sache:

let item = 12 
let item2:IntType = item 

die man dann, die offensichtlich aussehen wird ans Auge: Das wird nicht aus gutem Grund kompiliert.

let a = [1,2,3] 
let b: [IntType] = a 

Läßt die Größe jeder Art kontrollieren, bevor vorausfahr:

sizeofValue(item) //8 
sizeofValue(item2) //40 

Ein Array ein ansteckender Speicher von 8 Bytes ist. So ist Array ein ansteckender Speicher von 40 Bytes.

Wenn wir dies tun:

let b: [IntType] = a 

Wir sagen im Wesentlichen dem Compiler 8 Byte-Array in 40 Byte-Array zu konvertieren und zu speichern. Jetzt, da das Array ansteckend ist, muss es zerstören oder neu mischen, was eine teure Aufgabe ist. Dies behindert die Leistung und natürlich verliert man die Typensicherheit.

Der Compiler konnte dies aber diese Transformation Swift Team aus gutem Grund entschieden, dass der Benutzer explizit sein müssen, wenn sie aus 2 Gründen diese Art Transformation wollen: Leistung und Typ Sicherheit.

Verwandte Themen