无法在协议

时间:2017-04-04 18:09:45

标签: swift generics

我想知道我在这段代码中是否有一些简单的东西,或者它只是混合了一些阻止我做什么的Swift技巧我想要。

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

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

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

从Swift 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'的值输入' _?'

注意:这个问题的代码可以在游乐场测试。

1 个答案:

答案 0 :(得分: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类型。