关于 Opaque Return Type 和 Protocol with associatedtype In Swift 的一些问题
Some Problems about Opaque Return Type and Protocol with associatedtype In Swift
如何处理这个问题?
定义:
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...
}
以上代码为一些定义代码结构,请勿修改。
下面的函数有一些问题:
- 带有
asccociatedtype
的协议不能是字典值类型。
- Opaque 函数 Return 类型不能 return 一些不同的类型扩展相同的协议。
// <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))
}
}
有解决办法吗?
或列表中不同类型(具有嵌入泛型类型)的最佳实践。
您说不应修改定义,但这正是我在这里所做的:
我从 AnimalProtocol
协议中删除了关联类型,因为它没有在任何符合类型的其他地方使用
protocol AnimalProtocol {
var name: NameProtocol { get }
func cry() -> String
}
然后我通过将两者的 name
声明更改为
来更改 Cat
和 Dog
以符合协议
var name: NameProtocol
这解决了字典的问题,并且通过将 return 类型从 some AnimalProtocol
更改为 AnimalProtocol
来修复函数
如何处理这个问题?
定义:
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...
}
以上代码为一些定义代码结构,请勿修改。
下面的函数有一些问题:
- 带有
asccociatedtype
的协议不能是字典值类型。 - Opaque 函数 Return 类型不能 return 一些不同的类型扩展相同的协议。
// <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))
}
}
有解决办法吗? 或列表中不同类型(具有嵌入泛型类型)的最佳实践。
您说不应修改定义,但这正是我在这里所做的:
我从 AnimalProtocol
协议中删除了关联类型,因为它没有在任何符合类型的其他地方使用
protocol AnimalProtocol {
var name: NameProtocol { get }
func cry() -> String
}
然后我通过将两者的 name
声明更改为
Cat
和 Dog
以符合协议
var name: NameProtocol
这解决了字典的问题,并且通过将 return 类型从 some AnimalProtocol
更改为 AnimalProtocol