2015-10-17 24 views
12

Tôi muốn khởi tạo Tập hợp với các giá trị tương ứng với giao thức Hashable và một giao thức tùy chỉnh.Cài đặt và giao thức trong Swift

tôi đã cố gắng:

protocol CustomProtocol: Hashable {} 

let set = Set<CustomProtocol>() 

Nhưng Xcode phàn nàn:

Sử dụng 'CustomProtocol' như một loại bê tông phù hợp với giao thức 'Hashable' không được hỗ trợ

Làm thế nào có thể Tôi đạt được điều đó?

Xin cảm ơn trước.

+0

Đối tượng trong đã được yêu cầu để tuân theo Hashable. – Abizern

+0

Nếu CustomProtocol không tuân theo Hashable, Xcode phàn nàn về CustomProtocol không phù hợp với nó. Có vẻ như tôi đang thiếu thứ gì đó. –

Trả lời

8

Lý do ngay lập tức khiến bạn không thể làm những gì bạn muốn làm là Hashable là giao thức chung. Do đó nó - hoặc một giao thức xuất phát từ nó - không thể được sử dụng làm kiểu phần tử của Set. Một kiểu generic có thể chỉ được sử dụng như một ràng buộc trong một generic khác. Bạn sẽ nhận thấy rằng bạn cũng không thể khai báo một số Set<Hashable>, mặc dù loại phần tử của một bộ phải là tuân theo để có thể băm.

Cách tiếp cận đơn giản nhất là tạo, không phải là một tập hợp các giao thức, mà là một tập hợp một số loại đối tượng. Ví dụ, nếu S là một cấu trúc mà phù hợp với CustomProtocol (vì nó phù hợp với Hashable cộng bất cứ điều gì khác CustomProtocol đòi hỏi), bạn có thể khai báo một bộ S.

Ví dụ:

protocol CustomProtocol: Hashable { 

} 

func ==(lhs:S,rhs:S) -> Bool { 
    return lhs.name == rhs.name 
} 

struct S : CustomProtocol { 
    var name : String 
    var hashValue : Int { return name.hashValue } 
} 

let set = Set<S>() 

Nếu vấn đề bạn đang cố gắng giải quyết là bạn muốn có một tập hợp các kiểu hỗn hợp, tuy nhiên theo cách nào đó tương đương với nhau, thì đó chính là vấn đề được giải quyết bởi các phần mở rộng giao thức, như được giải thích trong phần thảo luận trong video định hướng WWDC 2015 .

Nhưng nó sẽ đơn giản hơn để làm cho tất cả các loại lớp học của bạn bắt nguồn từ NSObject. Bạn vẫn có thể làm cho chúng chấp nhận một số giao thức thứ cấp, tất nhiên, nhưng tập sẽ không được định nghĩa là một tập hợp của giao thức đó mà là của NSObject.

+0

Cảm ơn. Nhưng tôi muốn chèn vào các đối tượng đã đặt của tôi từ các lớp khác nhau, chứ không phải một lớp duy nhất. Đó là lý do tại sao tôi không muốn tạo ra một "bộ giao thức". –

+0

Xem câu trả lời đã sửa đổi của tôi. – matt

+0

Cách dễ nhất của khóa học là chỉ để làm cho tất cả các lớp học của bạn xuất phát từ NSObject, như bạn đã được thông báo. – matt

1

Trong Swift 3, một giải pháp là sử dụng AnyHashable structure.

Ví dụ, để tạo ra một nhà quan sát/mô hình quan sát được, chúng ta có thể làm:

protocol Observer { 
    func observableDidSomething(_ observable: Observable) 
} 

class Observable { 
    private var observersSet: Set<AnyHashable> = [] 

    private var observers: [Observer] { 
     return observersSet.flatMap { $0 as? Observer } 
    } 

    func add<O>(_ observer: O) where O : Observer, O : Hashable { 
     observersSet.insert(observer) 
    } 

    func remove<O>(_ observer: O) where O : Observer, O : Hashable { 
     observersSet.remove(observer) 
    } 

    // ... 

    private func doSomething() { 
     // do something ... 
     observers.forEach { $0.observableDidSomething(self) } 
    } 
} 

Chú ý rằng tôi tách các giao thức Hashable từ giao thức của tôi Observer.

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