从基类转换子类,其中子类在Swift中具有泛型

时间:2018-10-25 11:27:29

标签: ios swift generics subclass

我有一个基类类型和一个子类类型,其中子类包括一个泛型类型。如果我以基类类型的形式存储了子类,但是我想将其类型强制转换回子类类型,那么Swift似乎不会允许我。

以下是我的意思的示例:

class Base {

}

class Next<T> : Base where T : UIView {
    var view: T
    init(view: T) {
        self.view = view
    }
}

let a: [Base] = [Next(view: UIImageView()), Next(view: UILabel())]
for item in a {
    if let _ = item as? Next {
        print("Hey!")
    }
}

为什么"Hey!"从未打印过?


编辑:

如果强制转换显示为

"Hey!",则打印:

if let _ item as? Next<UIImageView> ...

但仅适用于UIImageView类。

如果数组"Hey!"中的一项为:

a将被打印

Next(view: UIView())

理想情况下,我不希望泛型转换时使用哪种类型,但是我意识到这可能是不可能的。

3 个答案:

答案 0 :(得分:4)

通用Next<T>是创建唯一的单独类的各种模板。 Next<UIView>Next<UIImageView>是两种完全不相关的类型。

您可以将它们与协议结合起来:

class Base {

}

class Next<T> : Base where T : UIView {
    var view: T
    init(view: T) {
        self.view = view
    }
}

protocol NextProtocol { }

extension Next: NextProtocol { }

let a: [Base] = [Next(view: UIImageView()), Next(view: UILabel()), Base()]
for item in a {
    if item is NextProtocol {
        print("Hey!")
    } else {
        print("Only a Base")
    }
}

输出:

Hey!
Hey!
Only a Base

通过定义诸如NextProcotol的协议,所有从Next<T>派生的类都应遵循,可以将它们称为一个组并将它们与从Base派生的其他类区分开。

注意:要检查item是否为类型,请使用is而不是检查条件强制转换as?是否有效。

答案 1 :(得分:0)

当我看到您的示例时,我期望它在编译过程中会失败。

似乎,只要为T指定一个具体的基类(在本例中为UIView),编译器就可以在Update Pallets SET CreatedDate = DATEADD(hour, -7, (Select CreatedDate from Pallets Where PalletNumber = 63)) as语句中推断该类。因此,当您键入is时,编译器会理解item as? Next Next`,因为UIView是一种具体类型。

如果使用协议而不是UIView,则此方法将无效。另外,仅使用item as?而不是Next(或Next<UIView>)将在Next<concrete subclass of UIView>is语句之外导致编译器错误。

答案 2 :(得分:0)

这是协议提供帮助的地方。

您需要一个虚拟协议来确认Next

并使用该虚拟协议检查您的商品类型。

因此,我们创建了一个虚拟协议以确认Next并使用该协议比较items

代码将是这样的。

class Base {

}

class Next<T> : Base where T : UIView {
    var view: T
    init(view: T) {
        self.view = view
    }
}
protocol  MyType  {

}

extension Next: MyType {}

let a: [Base] = [Next(view: UILabel()), Next(view: UILabel())]
for item in a {
    if let _ = item as? MyType {
        print("Hey!")
    }
}

UIView是所有UIElements的超类。

说这将成为真实的

if let _ = UILabel() as? UIView {print("yes") }

Next不会确认UIView,而是需要确认UIView的内容,因此您不能使用UIView的子项来检查它们是否为{ {1}},下一个没有确切类型,

这里我们使用上面的虚拟协议!