2014-12-03 3 views
2

У меня есть Свифт протокол, определяемый следующим образом:Далее сдерживая обобщенную функцию от Swift протокола

protocol MyProtocol { 
    func genericMethod<T:MyProtocol>(param:T) ->() 
} 

я могу реализовать универсальный метод в базовом классе, как это:

class MyBaseClass : MyProtocol { 
    func genericMethod<T where T:MyProtocol>(param:T) ->() { 
     println("Performing generic method for type \(T.self)") 
    } 
} 

class MySubClass : MyBaseClass { 
    ... 
} 

До сих пор , так хорошо. Я могу реализовать этот метод, и он компилируется и работает просто отлично.

Теперь я хочу сделать что-то подобное, но в моем базовом классе я хочу еще больше ограничить тип универсального метода, потребовав, чтобы он соответствовал протоколу, например Comparable. Я стараюсь это:

class MyBaseClass : MyProtocol { 
    func genericMethod<T where T:MyProtocol, T:Comparable>(param:T) ->() { 
     println("Performing generic method for type \(T.self)") 
    } 
} 

После того, как я добавить дополнительное ограничение на тип T, класс MyClass не будет компилироваться, так как он не соответствует протоколу больше.

Похоже, что добавление дополнительного ограничения на общий тип не должно приводить к его прекращению в соответствии с протоколом. Что мне не хватает? Мне кажется, что протокол говорит, что genericMethod должен быть передан параметр типа, который соответствует MyProtocol. Когда я иду осуществить это в MyBaseClass - только один из возможных вариантов реализации MyProtocol - что я должен быть в состоянии ограничить, что осуществление в дальнейшем, говоря, что параметр Myst соответствует Comparableв дополнении кMyProtocol

Есть ли способ уточнить общий тип в базовой реализации, как я пытаюсь сделать здесь?

+1

Я не понимаю, почему вы удивлены. Возможно, мне не хватает чего-то очевидного, но мне кажется, что в протоколе говорится: «Кто примет меня, должен реализовать« genericMethod »с параметром, являющимся его собственным типом. Но« T: MyBaseClass, T: Comparable »- это собственный тип MyBaseClass , поскольку MyBaseClass не использует Comparable, поэтому, как компилятор говорит, вы нарушили договор, установленный протоколом. – matt

+0

Использование ссылки 'Self' в протоколе было всего лишь одним из способов продемонстрировать проблему. проблема, если я использую один протокол, а затем другой. Я обновлю вопрос, чтобы было более понятно, почему я удивлен этим поведением –

+0

ОК, спасибо за ревизию. Ну, ответ на вопрос о том, почему компилятор не нравится это требование не соответствует. Требование к протоколу 'func genericMethod (param: T) ->()' не является тем же, что и 'func genericMethod (param: T) ->() '.Вы говорите в своеобразной ментальной оправдательной сноске «одна - более ограниченная версия другой», но это не имеет значения для компилятора; Дело в том, что это не одно. – matt

ответ

2

Добавление дополнительного ограничения на общем типе должна причины его прекратить в соответствии с протоколом, так как протокол должен гарантировать соответствие и соответствие не может быть гарантировано с подтипами, которые не Comparable. Если вы хотите, чтобы все MyProtocol объектов соответствовали Comparable, тогда вы должны сделать его частью определения MyProtocol.

protocol MyProtocol: Comparable { 
    //... 
} 

Я не пробовал, но это может также работать, если вы сделаете MyBaseClassComparable типа.

+0

Я не хочу, чтобы все объекты MyProtocol соответствовали Comparable. Я хочу, чтобы все подклассы «MyBaseClass» наследовали метод «genericFunction», который реализован с учетом того, что эти конкретные подклассы также соответствуют «Comparable». У меня будут другие базовые классы MyProtocol, которые реализуют протокол по-разному, не обязательно в зависимости от предположения, что их подклассы соответствуют 'Comparable' –

+0

. Затем вам нужно указать, что MyBaseClass соответствует Comparable. Содержит ли код, если вы это сделаете? –

0

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

protocol P { 
    func genericMethod<T where T:P, T:Comparable>(param:T) ->() 
} 

class C1 : P { 
    func genericMethod<T> (param:T) ->() {} // compiles even though omits Comparable 
    func test() { 
     genericMethod(C1()) // compiles even though C1 is not a Comparable 
    } 
} 
+1

Чувствуется как ошибка complier. –

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