[英]Dynamic member lookup with multiple keypaths for enums with associated values
Implementing dynamic member lookup on an enum with associated values leads to build errors when there is more than one keypath function.当存在多个键路径 function 时,在具有关联值的枚举上实现动态成员查找会导致构建错误。
I have an enum with multiple associates values, as described below:我有一个包含多个关联值的枚举,如下所述:
@dynamicMemberLookup
enum Media {
case movie(Movie)
case book(Book)
subscript<T>(dynamicMember keyPath: KeyPath<Entertainment, T>) -> T {
switch self {
case .movie(let movie):
return movie[keyPath: keyPath]
case .book(let book):
return book[keyPath: keyPath]
}
}
}
The structs Movie
and Book
inherit protocols Filmed
and Written
, which themselves inherit from the more generic protocol Entertainment
:结构
Movie
和Book
继承协议Filmed
和Written
,它们本身继承自更通用的协议Entertainment
:
protocol Entertainment {
var isbn: Int { get }
var title: String { get }
var sales: Int { get set }
}
protocol Written: Entertainment {
var author: String { get }
}
protocol Filmed: Entertainment {
var actors: [String] { get set }
}
struct Movie: Filmed {
var isbn: Int
var title: String
var sales: Int
var actors: [String]
}
struct Book: Written {
var isbn: Int
var title: String
var sales: Int
var author: String
}
So far, this works and has allowed me to access variables such as isbn
and title
, which are defined in Entertainment
, from the top-level Media
object through the subscript keypath lookup.到目前为止,这可行,并允许我通过下标 keypath 查找从顶级
Media
object 访问在Entertainment
中定义的变量,例如isbn
和title
。
let media: Media = .movie(Movie(isbn: 1011, title: "Top Gun", sales: 1000, actors: ["Tom Cruise", "Miles Teller"]))
print(media.title)
print(media.sales)
Now, when I try to add the subscript function below in Media
so that I can optionally access variables conforming to either Filmed
or Written
, I receive an error for the above print statements stating Ambiguous use of 'subscript(dynamicMember:)'
现在,当我尝试在下面的
Media
中添加下标 function 以便我可以选择访问符合Filmed
或Written
的变量时,我收到上述打印语句的错误,说明Ambiguous use of 'subscript(dynamicMember:)'
subscript<T>(dynamicMember keyPath: KeyPath<Filmed, T>) -> T? {
switch self {
case .movie(let movie):
return movie[keyPath: keyPath]
default:
return nil
}
}
In this example, the build errors are as follows:在此示例中,构建错误如下:
let media: Media = .movie(Movie(isbn: 1011, title: "Top Gun", sales: 1000, actors: ["Tom Cruise", "Miles Teller"]))
print(media.title) // BUILD ERROR: Ambiguous use of 'subscript(dynamicMember:)'
print(media.sales) // BUILD ERROR: Ambiguous use of 'subscript(dynamicMember:)'
print(media.actors) // This doesn't throw an error and successfully logs
When I remove the second subscript function, the build errors are gone.当我删除第二个下标 function 时,构建错误消失了。
Please let me know if I'm doing anything wrong in my implementation here.如果我在此处的实施中做错了什么,请告诉我。
Figured out the answer:想出了答案:
By changing Filmed
and Written
to no longer conform to Entertainment
, the build errors were removed.通过将
Filmed
和Written
更改为不再符合Entertainment
,构建错误被删除。 The code as following now works:以下代码现在可以工作:
protocol Entertainment {
var isbn: Int { get }
var title: String { get }
var sales: Int { get set }
}
protocol Written {
var author: String { get }
}
protocol Filmed {
var actors: [String] { get set }
}
struct Movie: Entertainment, Filmed {
var isbn: Int
var title: String
var sales: Int
var actors: [String]
}
struct Book: Entertainment, Written {
var isbn: Int
var title: String
var sales: Int
var author: String
}
@dynamicMemberLookup
enum Media {
case movie(Movie)
case book(Book)
subscript<T>(dynamicMember keyPath: KeyPath<Entertainment, T>) -> T {
switch self {
case .movie(let movie):
return movie[keyPath: keyPath]
case .book(let book):
return book[keyPath: keyPath]
}
}
subscript<T>(dynamicMember keyPath: KeyPath<Filmed, T>) -> T? {
switch self {
case .movie(let movie):
return movie[keyPath: keyPath]
default:
return nil
}
}
}
Here is the output of the print statements:这是打印语句的 output:
let media: Media = .movie(Movie(isbn: 1011, title: "Top Gun", sales: 1000, actors: ["Tom Cruise", "Miles Teller"]))
print(media.title) // OUTPUT: "Tom Cruise"
print(media.sales) // OUTPUT: 1000
print(media.actors) // OUTPUT: Optional<[String]>: ["Tom Cruise", "Miles Teller"]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.