【问题标题】:Some Problems about Opaque Return Type and Protocol with associatedtype In SwiftSwift 中关于不透明返回类型和关联类型协议的一些问题
【发布时间】:2021-10-08 09:58:28
【问题描述】:

如何处理这个问题?

定义:

protocol NameProtocol {
    var rawValue: String { get }
}
struct CatName: NameProtocol {
    enum CatNamesEnum: String {
        case Tiger, Max, Sam
    }
    var literal: CatNamesEnum
    var rawValue: String {
        literal.rawValue
    }
}
struct DogName: NameProtocol {
    enum DogNamesEnum: String {
        case Jack, Toby, Sadie
    }
    var literal: DogNamesEnum
    var rawValue: String {
        literal.rawValue
    }
}

定义:

protocol AnimalProtocol {
    associatedtype Name: NameProtocol
    var name: Name { get }
    func cry() -> String
}
class Cat: AnimalProtocol {
    var name: CatName
    func cry() -> String {
        return "meow, I am \(name.rawValue)"
    }
    init(name: CatName) {
        self.name = name
    }
    // some other cat actions...
}
class Dog: AnimalProtocol {
    var name: DogName
    func cry() -> String {
        return "bark, I am \(name.rawValue)"
    }
    init(name: DogName) {
        self.name = name
    }
    // some other dog actions...
}

以上代码是一些定义代码结构,请勿修改。

下面的函数有一些问题:

  1. 带有asccociatedtype 的协议不能是字典值类型。
  2. 具有不透明返回类型的函数无法返回某些不同类型的扩展相同协议。
// <1>
// Error: Protocol 'AnimalProtocol' can only be used as a generic constraint because it has Self or associated type requirements

let animals: [String: AnimalProtocol] = [
    "cat": Cat(name: CatName(literal: .Sam)),
    "dog": Dog(name: DogName(literal: .Jack))
        // ...
        // maybe a lot of animals
]
for (animal, entity) in animals {
    print("\(animal): \(entity.cry())")
}
// <2> 
// Error: Function declares an opaque return type, but the return statements in its body do not have matching underlying types
func animalCry(animal: String) -> some AnimalProtocol {
    switch animal {
    case "cat":
        return Cat(name: CatName(literal: .Sam)) 
    default:
        return Dog(name: DogName(literal: .Toby)) 
    }
}

有什么解决办法吗? 或列表中不同类型(嵌入泛型类型)的最佳实践。

【问题讨论】:

    标签: swift generics swift-protocols associated-types


    【解决方案1】:

    你说不应该修改定义,但这正是我在这里所做的:

    我从 AnimalProtocol 协议中删除了关联类型,因为它没有在任何符合类型的其他地方使用

    protocol AnimalProtocol {
        var name: NameProtocol { get }
        func cry() -> String
    }
    

    然后我将CatDog 都更改为符合协议,方法是将两者中的name 声明更改为

    var name: NameProtocol
    

    这解决了字典的问题,并且通过将返回类型从 some AnimalProtocol 更改为 AnimalProtocol 来修复函数

    【讨论】:

      猜你喜欢
      • 2022-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多