[英]Dynamic member lookup with multiple keypaths for enums with associated values
當存在多個鍵路徑 function 時,在具有關聯值的枚舉上實現動態成員查找會導致構建錯誤。
我有一個包含多個關聯值的枚舉,如下所述:
@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]
}
}
}
結構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
}
到目前為止,這可行,並允許我通過下標 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)
現在,當我嘗試在下面的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
}
}
在此示例中,構建錯誤如下:
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
當我刪除第二個下標 function 時,構建錯誤消失了。
如果我在此處的實施中做錯了什么,請告訴我。
想出了答案:
通過將Filmed
和Written
更改為不再符合Entertainment
,構建錯誤被刪除。 以下代碼現在可以工作:
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
}
}
}
這是打印語句的 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.