2015-06-10 27 views
21

Kể từ Swift 2.0 có vẻ như chúng ta có thể tiến gần hơn đến các phần mở rộng của các kiểu generic áp dụng cho các tình huống được xác định trước.Swift "where" Array Extensions

Mặc dù chúng tôi vẫn không thể làm điều này:

protocol Idable { 
    var id : String { get } 
} 

extension Array where T : Idable { 
    ... 
} 

... bây giờ chúng ta có thể làm điều này:

extension Array { 
    func filterWithId<T where T : Idable>(id : String) -> [T] { 
    ... 
    } 
} 

... và Swift ngữ pháp chấp nhận nó. Tuy nhiên, đối với cuộc sống của tôi, tôi không thể tìm ra cách làm cho trình biên dịch hài lòng khi tôi điền vào các nội dung của hàm ví dụ. Giả sử tôi được như rõ ràng càng tốt:

extension Array { 
    func filterWithId<T where T : Idable>(id : String) -> [T] { 
     return self.filter { (item : T) -> Bool in 
      return item.id == id 
     } 
    } 
} 

... trình biên dịch sẽ không chấp nhận việc đóng cửa được cung cấp để lọc, phàn nàn

Không thể gọi 'lọc' với một danh sách đối số kiểu ' ((T) -> Bool) '

Tương tự nếu mục được chỉ định là Đáng tin cậy. Có ai may mắn ở đây không?

Trả lời

37
extension Array { 
    func filterWithId<T where T : Idable>(id : String) -> [T] { 
    ... 
    } 
} 

định nghĩa một phương pháp chung filterWithId() nơi generic placeholder T bị hạn chế là Idable. Nhưng định nghĩa đó giới thiệu một trình giữ chỗ cục bộ T hoàn toàn không liên quan đến loại phần tử mảng T (và ẩn trong phạm vi của phương pháp).

Vì vậy, bạn có không đã xác định rằng các phần tử mảng phải phù hợp để Idable, và đó là lý do tại sao bạn không thể gọi self.filter() { ... } với một kết thúc mà hy vọng các yếu tố là Idable.

Tính Swift 2/Xcode 7 beta 2, bạn có thể xác định phương pháp khuyến nông trên một loại chung chung mà là hạn chế hơn trên mẫu (so sánh Array extension to remove object by value cho một vấn đề rất tương tự):

extension Array where Element : Idable { 

    func filterWithId(id : String) -> [Element] { 
     return self.filter { (item) -> Bool in 
      return item.id == id 
     } 
    } 
} 

Ngoài ra, bạn có thể xác định một phương pháp khuyến nông giao thức:

extension SequenceType where Generator.Element : Idable { 

    func filterWithId(id : String) -> [Generator.Element] { 
     return self.filter { (item) -> Bool in 
      return item.id == id 
     } 
    } 
} 

Sau đó filterWithId() hiện có sẵn cho tất cả các loại phù hợp đến SequenceType (cụ thể là Array) nếu phần tử trình tự loại phù hợp với Idable.

Trong Swift 3 này sẽ

extension Sequence where Iterator.Element : Idable { 

    func filterWithId(id : String) -> [Iterator.Element] { 
     return self.filter { (item) -> Bool in 
      return item.id == id 
     } 
    } 
} 
+0

Ah có ý nghĩa cảm giác hoàn hảo, cảm ơn bạn cho việc học tập :) –

+0

@ yo.ian.g: Bạn được hoan nghênh! –

+0

Có cách nào để làm điều này với các loại không giao thức, như 'mở rộng mảng nơi Iterator.Element: CGRect'? –

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