【发布时间】:2019-04-13 13:16:18
【问题描述】:
所以我有一个基类DataViewController<T>,它继承自UITableViewController,如下所示:
class DataTableViewController<T : BMPage<BMData>> : UITableViewController, UISearchBarDelegate {
// implementations...
}
我还有一个 TournamentsViewController,它继承自 DataViewController 并传入了泛型:
class TournamentsViewController: DataTableViewController<TournamentPage> {
// overrides, etc.
}
供参考,这里是BMPage<T>:
open class BMPage<T : Codable> : Decodable {
public enum CodingKeys: String, CodingKey {
case data
}
var data : [T]
required public init(from decoder:Decoder) throws {
let vals = try decoder.container(keyedBy: CodingKeys.self)
data = try vals.decode([T].self, forKey: .data)
}
}
extension BMPage: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(data, forKey: .data)
}
}
...和BMData:
open class BMData : Codable {
public enum CodingKeys: CodingKey {
case id
case name
}
var id: Int
var name: String
required public init(from decoder:Decoder) throws {
let vals = try decoder.container(keyedBy: CodingKeys.self)
id = try vals.decode(Int.self, forKey: .id)
name = try vals.decode(String.self, forKey: .name)
}
}
我想要实现的目标:各种UITableViewController 子类,它们只需要指定泛型即可指定其特定数据。以下是我的 Tournament 和 TournamentPage 实现,应该更好地解释这个概念:
open class Tournament : BMData {
let game_id: Int = 0
let game_iteration_id: Int = 0
let state: Int = 0
let starts_at: String = ""
let creator_id: Int = 0
let stream_url: String? = nil
let entrant_count: Int = 0
let prereg_count: Int = 0
let path: String = ""
}
open class TournamentPage : BMPage<BMData> {
public enum CodingKeys: String, CodingKey {
case data = "tournaments"
}
let page: String? = nil
let results_per_page: String = ""
let tournament_count: Int = 0
}
问题:编译器不喜欢我这样做,因为它会抛出多个但非常相似的错误,例如:
Cannot convert return expression of type 'TournamentsViewController' to return type 'UIViewController'Cannot convert return expression of type 'TournamentsViewController?' to return type 'UIViewController?'
这里是这样一个表达式的示例(取自 XCode 在那里输入的默认 ModelController,这是所有这些错误发生的地方:
let dataViewController = storyboard.instantiateViewController(withIdentifier: "DataViewController") as! TournamentsViewController
有没有办法实现我想要做的事情?我承认,我是 Swift 新手(这周才开始学习),所以也许我完全误解了典型的 Swift 实践以及它的设计目的,但是用 C# 之类的语言实现了这一点(可能甚至是 Objective-C,虽然我对它有点生疏,因为我上次使用它已经有一段时间了)这几乎就是我在这里所做的。
【问题讨论】:
标签: ios swift oop generics inheritance