2015-04-02 15 views
6

Với mã này:Làm cách nào để gọi thuộc tính tĩnh trên giao thức Swift từ một hàm chung?

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ôi nhận được một lỗi trên dòng trở lại: "Không thể chuyển đổi biểu hiện trở lại của loại 'T.T' để dự đoán kiểu trả về 'T'".

Thay đổi thành return T.defaultValue as! T dường như hoạt động nhưng điều đó không có ý nghĩa với tôi. Tôi có thiếu cái gì hay tôi nên ghi một radar?

Trả lời

7

Bạn có thể sử dụng Self trong giao thức:

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 
} 

OR, nếu bạn muốn sử dụng typealias, bạn phải:

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

Aha, vì việc khai báo hàm chung không biết T là gì (ít nhất là lúc nào? Hay ít nhất là lúc không biên dịch) nhưng giao thức có? Hay đại loại thế? –

+0

Vâng, trong mã của bạn, hàm 'selected' không biết loại' typealias T' thực sự là gì. 'T' trong hàm' đã chọn' và 'T' trong' Có thể chọn' không liên quan. – rintaro

1

Xây dựng về câu trả lời @ rintaro của, sử dụng Self đối với loại defaultValue có nghĩa là typealias là không cần thiết:

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 
} 

(Tôi thấy điều này như thay đổi defaultValue 's loại để Self khiến lớp thực hiện của tôi không phù hợp với các giao thức nữa và tôi nhận thấy tôi đã thậm chí không đề cập đến typealias Value; loại bỏ điều đó làm cho lớp triển khai của tôi tuân thủ một lần nữa.)

Các vấn đề liên quan