2015-04-02 21 views
6

鉴于这种代码:如何从通用函数调用Swift协议的静态属性?

public protocol Selectable { 

    typealias T 

    var selected: Bool { get } 

    static var defaultValue: T { get } 

} 

public func selected<T: Selectable>(items: [T]) -> T { 
    if let selected = items.filter({$0.selected}).first { 
     return selected 
    } 
    return T.defaultValue 
} 

我上回行的错误:“无法将类型的返回表达式‘T.T’预期收益型‘T’”。

更改为return T.defaultValue as! T似乎工作,但这对我没有任何意义。我错过了什么,或者我应该提交一个雷达?

回答

7

您可以在协议中使用Self

public protocol Selectable { 

    var selected: Bool { get } 

    static var defaultValue: Self { get } 
    //      ^^^^ 
} 

public func selected<T: Selectable>(items: [T]) -> T { 
    if let selected = items.filter({$0.selected}).first { 
     return selected 
    } 
    return T.defaultValue 
} 

,或者,如果你想使用typealias,你必须:

public protocol Selectable { 
    typealias Value 

    var selected: Bool { get } 

    static var defaultValue: Value { get } 
} 

public func selected<T: Selectable where T.Value == T>(items: [T]) -> T { 
    //        ^^^^^^^^^^^^^^^^^^ 
    if let selected = items.filter({$0.selected}).first { 
     return selected 
    } 
    return T.defaultValue 
} 
+0

啊,因为泛型函数的声明不知道T是什么(根本不是在编译时,或者至少不是在编译时),但协议呢?或类似的东西? – 2015-04-02 14:39:32

+0

是的,在你的代码中'selected'函数不知道'typealias T'的实际类型是什么。 'selected'函数中的'T'和'Selectable'中的'T'不相关。 – rintaro 2015-04-02 14:51:51

1

大厦@林太郎的答案,使用Self对于类型defaultValue意味着typealias是不必要的:

public protocol Selectable { 

    var selected: Bool { get } 

    static var defaultValue: Self { get } 

} 

public func selected<T: Selectable >(items: [T]) -> T { 
    if let selected = items.filter({$0.selected}).first { 
     return selected 
    } 
    return T.defaultValue 
} 

(我发现这是改变defaultValue的类型Self让我实现类不符合协议了,我发现我不是连指typealias Value;删除,这使得我的实现类再次符合。)