2017-09-03 144 views
1

是否可以在另一協議的通用功能中提供確認協議? 我試着讓它像這樣工作,但這是不可能的,或者我犯了一些錯誤。協議與通用功能的關聯類型協議

我的代碼:

protocol DataModelProtocol { 
    associatedtype ObjectProtocol: Protocol 
    func fetchObjects<T: ObjectProtocol>() -> [T]? 
    func fetch<T: ObjectProtocol>(object: T) -> T? 
    func delete<T: ObjectProtocol>(allObjectOf type: T.Type) 
    func insert<T: ObjectProtocol>(_ object: T) 
    func save<T: ObjectProtocol>(_ object: T) 
    func update<T: ObjectProtocol>(_ object: T) 
    func delete<T: ObjectProtocol>(_ object: T) 
} 

錯誤消息:

從非協議,非類類型'Self.ObjectProtocol的繼承

Image of Xcode error

它作品只是這樣,但我想讓它更靈活:

protocol DataModelProtocol { 
    typealias ObjectProtocol = NSManagedObject 
    ... 
} 

回答

1

這便叫更容易的是你將返回類型的責任賦予了對象類本身。

您將需要兩個協議,但它會避免混合協議和仿製藥:

// The first protocol is for the base class of data objects 
protocol DataProtocol 
{} 

// The protocol provides the "typed" equivalents of the model's 
// data manipulation methods. 
// By using an extension to DataProtocol, this only needs to 
// be done once for all models and data objects. 
extension DataProtocol 
{ 
    static func fetchObjects(from model:DataModelProtocol) -> [Self]? 
    { return model.fetchObjects(object: Self.self) as! [Self]? } 

    static func fetch(from model:DataModelProtocol) -> Self? 
    { return model.fetch(object: Self.self) as! Self? } 

    // ... 
} 

// The second protocol is for the data models 
// It requires implementation of the data manipulation methods 
// using the general "DataProtocol" rather than any specific class 
// The actual instances it produces must be of the appropriate class 
// however because they will be type casted by the DataProtocol's 
// default methods 
protocol DataModelProtocol 
{ 
    func fetchObjects(object:DataProtocol.Type) -> [DataProtocol]? 
    func fetch(object:DataProtocol.Type) -> DataProtocol? 
    // ... and so on 
} 

... 這裏的協議可以如何使用簡單的(幼稚)的例子。 (我故意選擇不使用核心數據來說明解決方案的一般性) ...

// The base class (or each one) can be assigned the DataProtocol 
// (it doesn't add any requirement) 

class LibraryObject : DataProtocol 
{} 

class Author: LibraryObject 
{ 
    var name = "" 
} 

class Book: LibraryObject 
{ 
    var title = "" 
} 

// This is a simple class that implements a DataModelProtocol 
// in a naive (and non-core-data way) 

struct LibraryModel:DataModelProtocol 
{ 
    var authors:[Author] = [ Author(), Author() ] 

    var books:[Book] = [ Book(), Book(), Book(), Book(), Book() ] 

    func fetchObjects(object: DataProtocol.Type) -> [DataProtocol]? 
    { 
    return object == Book.self ? books 
      : object == Author.self ? authors 
      : nil 
    } 

    func fetch(object:DataProtocol.Type) -> DataProtocol? 
    { return nil } 

} 

... 使用的協議將是你的做法有點不同,因爲你會從首發對象類,而不是將它們作爲參數傳遞給模型 ...

var library = LibraryModel() 
let allBooks = Book.fetchObjects(from:library) // this almost reads like english 
0

如果想要另一個協議的通用功能要符合,只是簡單地創建T符合該協議,無需進行額外的ObjectProtocolassociatedType

​​
+0

如果我會讓這樣的,它將與 一個類型只工作比如我想使用的功能父母和孩子,取其中的工作是NSManagedObject Bu的子類t在這個解決方案中,我總是會得到NSManagedObject –

+0

@YerkebulanAbildin爲什麼? – paper1111