[英]Swift: Assigning an object of type sub class to a variable of type base class with generics produces error
I want to assign a sub class ( TapWhatYouHearViewController ), that inherits from its parent class ( BaseLectureViewController ) with implementing the generic using an inherited type ( TapWhatYouHear ), to a variable of type parent class ( BaseLectureViewController ) with the generic of type base class ( Game ). 我想分配一个子类 ( TapWhatYouHearViewController ),它继承自其父类 ( BaseLectureViewController ),使用继承类型 ( TapWhatYouHear )实现泛型,使用类型基类的泛型类型的父类 ( BaseLectureViewController )类型的变量( 游戏 )。
Swift procudes the following error: Swift会产生以下错误:
Swift:: Error: cannot assign value of type 'TapWhatYouHearViewController' to type 'BaseLectureViewController?'
Swift :: Error:无法指定类型'TapWhatYouHearViewController'的值来键入'BaseLectureViewController?'
I've read, that one solution eg in Java would be using a wildcard generic, but this is not possible in Swift. 我已经读过,例如Java中的一个解决方案将使用通配符泛型,但这在Swift中是不可能的。 Is there any other solution?
还有其他解决方案吗?
This is my setup: 这是我的设置:
/** GAME TYPES **/
enum GameType {
case TapWhatYouHear,
case ChooseTranslation
}
class Game {
var title: String?
var type: GameType?
}
class TapWhatYouHear : Game {
var audio: String?
var type: GameType = GameType.TapWhatYouHear
}
class ChooseTranslation : Game {
var video: String?
var type: GameType = GameType.ChooseTranslation
}
/** VIEW CONTROLLERS **/
class BaseLectureViewController<T: Game> {
var game: T?
}
class TapWhatYouHearViewController : BaseLectureViewController<TapWhatYouHear> {
}
class ChooseTranslationViewController : BaseLectureViewController<ChooseTranslation> {
}
I want to do the following: 我想做以下事情:
var game: Game = TapWhatYouHear() // <-- Depending on the user interaction, this can be any sub class of "Game"
var viewController: BaseLectureViewController<Game>
switch game.type {
case .ChooseTranslation:
viewController = TapWhatYouHearViewController() // <--Swift:: Error: cannot assign value of type 'TapWhatYouHearViewController' to type 'BaseLectureViewController<Game>?'
case .TapWhatYouHear:
viewController = ChooseTranslationViewController()
}
viewController.game = TapWhatYouHear()
What I'm trying to do is determine at runtime which sub class of BaseLectureViewController
should be assigned to the viewController
variable. 我要做的是在运行时确定应该将哪个
BaseLectureViewController
子类分配给viewController
变量。 To save code, I then want to assign a game of type Game
to the game
property of the BaseLectureViewController
. 为了保存代码,我想要将
Game
类型的Game
分配给BaseLectureViewController
的game
属性。
The generic approach you have in mind is not possible. 您想到的通用方法是不可能的。 My suggestion is to go with a simple inheritance solution where you override
getGame()
in your concrete ViewController (ie TapWhatYouHearViewController
) and cast the game to your specific type. 我的建议是使用一个简单的继承解决方案,你在具体的ViewController中重写
getGame()
(即TapWhatYouHearViewController
)并将游戏转换为你的特定类型。
import UIKit
enum GameType {
case TapWhatYouHear
case ChooseTranslation
}
class Game {
var title: String?
var type: GameType?
}
class TapWhatYouHear : Game {
var audio: String?
override init() {
super.init()
type = GameType.TapWhatYouHear
}
}
class ChooseTranslation : Game {
var video: String?
override init() {
super.init()
type = GameType.ChooseTranslation
}
}
/** VIEW CONTROLLERS **/
protocol Lecture {
var game: Game? { get set }
}
class BaseLectureViewController: UIViewController, Lecture {
var game: Game?
func getGame() -> Game? {
fatalError("Must be implemented in subclass")
}
}
class TapWhatYouHearViewController : BaseLectureViewController {
override func getGame() -> TapWhatYouHear? {
return game as? TapWhatYouHear
}
}
class ChooseTranslationViewController : BaseLectureViewController {
override func getGame() -> ChooseTranslation? {
return game as? ChooseTranslation
}
}
var game: Game = TapWhatYouHear() // <-- Depending on the user interaction, this can be any sub class of "Game"
var viewController: BaseLectureViewController?
if let gameType = game.type {
switch gameType {
case GameType.ChooseTranslation:
viewController = TapWhatYouHearViewController() // <--Swift:: Error: cannot assign value of type 'TapWhatYouHearViewController' to type 'BaseLectureViewController<Game>?'
case GameType.TapWhatYouHear:
viewController = ChooseTranslationViewController()
}
viewController?.game = TapWhatYouHear()
}
Change the variable declaration to 将变量声明更改为
var viewController: BaseLectureViewController<TapWhatYouHear>
Or skip generics and declare your super class as 或者跳过泛型并将你的超级类声明为
class BaseLectureViewController {
var game: Game?
}
If all you want to do is to assign a game
property with an instance of specific subclass of Game
, then you might use something like this, omitting generics 如果您要做的就是为
game
属性分配一个特定的Game
子类实例,那么您可以使用类似的东西,省略泛型
class Game {
var title: String?
required init() {}
}
class TapWhatYouHear : Game {
var audio: String?
}
class ChooseTranslation : Game {
var video: String?
}
/** VIEW CONTROLLERS **/
class BaseLectureViewController : UIViewController {
var game: Game
init(gameType: Game.Type)
{
game = gameType.init()
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class TapWhatYouHearViewController : BaseLectureViewController{
init()
{
super.init(gameType: TapWhatYouHear.self)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class ChooseTranslationViewController : BaseLectureViewController{
init()
{
super.init(gameType: ChooseTranslation.self)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
usage 用法
var viewController : BaseLectureViewController
viewController = TapWhatYouHearViewController()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.