2017-04-04 47 views
2

我想知道是否有简单的东西,我在这里代码丢失,或者它只是一个混合的Swift技巧,阻止我做我想做的事情。无法分配到通用属性协议

我允许实现Foo协议类型包含任何类型的entity属性,只要它符合StringIdentifiable

protocol StringIdentifiable { 
    var id: String? { get } 
} 

protocol Foo: class { 
    associatedtype AnyStringIdentifiable: StringIdentifiable 
    var entity: AnyStringIdentifiable? { get set } 
} 

作为夫特3.1,这种“任何类型的”部分wouldn't be possible如果不使用associatedtype。继续,假设我有另一个需要Foo属性的协议。但是,Foo是通用的,因此您可能知道我们不能这样做,因为“通用协议只能用作通用约束”。试图避免类型擦除一塌糊涂,我决定在我的第二个协议使用另一个associatedtype和编译器不抱怨:

protocol Bar { 
    //var foo: Foo { get set } // can't do because Foo is generic 
    associatedtype AnyFoo: Foo 
    var foo: AnyFoo { get set } 
} 

但现在,如果我尝试设置在foo东西,编译器会抱怨:

extension Bar { 
    func setEntity(_ entity: StringIdentifiable) { 
    foo.entity = entity 
    } 
} 

的错误是无法分配型“StringIdentifiable”到类型的值“_?”

注意:这个问题的代码是可以在操场上测试的。

回答

3

你可以像下面这样做

//: Playground - noun: a place where people can play 

import Cocoa 

protocol StringIdentifiable { 
    var id: String? { get } 
} 

protocol Foo: class { 
    associatedtype AnyStringIdentifiable: StringIdentifiable 
    var entity: AnyStringIdentifiable? { get set } 
} 

protocol Bar { 
    //var foo: Foo { get set } // can't do because Foo is generic 
    associatedtype AnyFoo: Foo 
    var foo: AnyFoo { get set } 
} 

extension Bar { 
    func setEntity(_ entity: AnyFoo.AnyStringIdentifiable) { 
     foo.entity = entity 
    } 
} 

在酒吧,你可以使用AnyFoo.AnyStringIdentifiable以确保设置foo.entity当类型是正确的,因为foo.entity的类型是AnyFoo.AnyStringIdentifiable的。

+1

哈哈听起来很hacky,但它的工作:) – Gobe

+0

这只是类型系统帮助你!想想吧 - 对于一个给定的Bar,你知道它有一个'AnyFoo',它是一个'Foo'。 AnyFoo有一个总是一个StringIdentifiable的AnyStringIdentifiable。仅仅因为两件事都是“AnyFoo”,并不意味着它们共享相同的“AnyStringIdentifiable”。所以你从Bar'的角度来看没有足够的知识来知道你需要什么类型的'StringIdentifiable'。但是'Bar'知道它有什么类型的'Foo',并且'Foo'知道它有什么类型的'StringIdentifiable'。所以你必须这样解决它:'AnyFoo.AnyStringIdentifiable'。 –

+0

现在我不同意......首先,任何东西都是关联类型。我不喜欢我能够在协议本身之外引用这些类型的事实。能够从Bar内部调用AnyStringIdentifiable非常奇怪。其次,我相信从酒吧的角度来看有足够的知识,Bar知道它有一些是Foo和Foos有一些是StringIdentifiable的东西。他们面前有“任何”(作为相关类型)的事实使其更加通用(尽管如果SR-522已被解决,则不需要) – Gobe