2015-01-05 3 views
3

Я пытаюсь с помощью расширения для существующего класса с методом класса, как:Как использовать протокол с дополнительными методами класса в расширении с общим в Swift?

@objc public protocol MyProtocol { 
    optional class func foo() -> Int 
} 

И я использую этот протокол в расширении с родовым, как:

extension MyClass { 

    public func bar<T: MyProtocol>() { 
     ... 
     let x: Int = T.self.foo!() // if I do not use "self" or "!" here, I will have a compiler error 
     ... 
    } 

Это должно работать, но когда я строю он, Xcode говорит: «Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc не удалось с кодом выхода 1». Если я не использую «необязательный» в протоколе, мне не нужно разворачивать foo() в расширении, и все работает хорошо, даже если я удалю «я». Может ли кто-нибудь сказать мне, почему и как сделать дополнительную работу правильно? Спасибо заранее.

ответ

2

Похоже, что вы обнаружили (довольно неясную) ошибку в компиляторе Swift, из-за которого он разбился. Вот репродукция, что все, что нужно в одном файле врезаться swiftc:

import Foundation 
@objc protocol P { optional class func f() } 
func f<T: P>(t: T) { T.self.f?() } 

(вам не нужно вызывать f для того, чтобы врезаться)

Вы должны, вероятно, файл радар с компилятором сбой никогда не ожидается поведение независимо от вашего кода.

Если вы попытались сделать это без optional, это сработает (и вы даже можете опустить self). Я предполагаю, что реализация дженериков в настоящее время не учитывает возможность дополнительных функций уровня класса.

Вы можете сделать это без дженериков, как это:

func f(p: MyProtocol) { 
    (p as AnyObject).dynamicType.foo?() 
} 

(может даже быть лучше, но я не могу определить его).

Вам нужен AnyObject бросок, потому что если вы пытаетесь вызвать .dynamicType.foo?() на p непосредственно вы получите «доступ к членам протокола значения типа„MyProtocol.Type“является невыполненным». Я не удивлюсь, если с этим связано сбой общей версии.

Я бы также сказал, что его стоит спросить себя, действительно ли вам нужен протокол с дополнительными методами (особенно на уровне класса), и есть ли способ сделать то, что вы хотите полностью статически, используя generics (как вы уже пол-делать).

+0

Практический код об этом намного сложнее. Именно так я оптимизирую дизайн использования Alamofire с маршрутизатором. Это нормально, чтобы не использовать необязательный (всего пару дополнительных строк), но проблема действительно смутила меня. Спасибо вам за разъяснение! – Wizard

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