2016-06-14 3 views
0

У меня возникла проблема с компиляцией тестов в Swift. Похоже, что компилятор теряет информацию о типе шаблона, но другие общие методы работают нормально. Что мне не хватает?Функция swift generic не компилируется при тестировании

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)' 
    } 
} 

Update

MatchNormElement является протоколом, поэтому я изменил его к конкретному типу. Теперь это работает.

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

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

Я заменил 'MatchNormElement' и' LinearTransformation' на 'NSString' (и удалил' resol2', этот метод не нужен для поиска), и ошибок компиляции нет. Возможно, эта информация поможет вам. –

+0

Спасибо ShadowOf. MatchNormElement - это протокол. И это похоже, что список должен иметь конкретные типы. –

ответ

1

Это разумно для компилятора. Swift позволяет преобразование типов для типа Concrete для назначения переменной на основе протокола.

Однако Swift не позволяет преобразовывать набор конкретных типов в набор/массив протокола путем преобразования каждого из них. Это разумно из-за следующих причин:

Пусть Предположим, у нас есть это создает на месте:

protocol IntType {} 
extension Int: IntType{} 

Теперь давайте делать очевидную вещь:

let item = 12 
let item2:IntType = item 

Тогда тот, который будет выглядеть очевидным к глазу: Это не скомпилируется по уважительной причине.

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

Позволяет проверить размер каждого типа, прежде чем двигаться вперед:

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

Массив является заразной памяти 8 байт. Так же Array представляет собой заразную память в 40 байт.

Когда мы сделали это:

let b: [IntType] = a 

Мы по существу сказать компилятору, чтобы преобразовать 8 байт массива в 40 байт массива и хранить его. Теперь, поскольку массив заразителен, он должен разрушить или перетасовать, что является дорогостоящей задачей для этого. Это мешает производительности и, очевидно, вы теряете безопасность типа.

компилятор мог это такое преобразование, но Swift команда решила по уважительной причине, что пользователю нужно быть явным, если они хотят этот тип преобразования для 2 причинам: Производительность и типобезопасность.

Смежные вопросы