为什么我必须在swift

时间:2016-02-23 02:59:25

标签: swift

我有以下 - 简化 - 代码:

class A {
    var x: Int = 9

}

class B: A {
    var y: Int = 8
}


class S {
    var myList = [A]()
}


//class T: S {
//    override var myList = [B]()
//}

class V: S {

    func foo() {
        let bar = myList[2] as! B
        print(bar.y)
    }
}

在swift 2.1中我必须使用as!或者我得到A不能转换为B的错误消息。我应该强制转换到子类似乎是错误的,但也许我错过了一些东西。

注释掉的部分是我的第一次尝试,但是不会使用myList类型' [B]'无法覆盖类型为' [A]'的属性

在这两种情况下,我都不理解这种行为,因为B显然是A的子类。

  1. 有人可以解释为什么我不能覆盖声明吗?
  2. 有人可以解释为什么我必须强迫垂头丧气吗?
  3. 谢谢!

1 个答案:

答案 0 :(得分:0)

对于point(1),您根本不能覆盖存储的属性,只能覆盖计算属性。此外,即使您覆盖计算属性,也不能像在此处尝试那样给它一个不同的类型。而且由于您无法更改类型,因此覆盖存储的属性实际上没有任何意义 - 您将覆盖的内容是什么?如果它是超类中的int和子类中的int,或者超类中的[A]以及子类中的[A],那么你就是&#39} ; t实际上通过覆盖它来改变任何东西。您可以通过覆盖计算属性来更改行为,但显然不能使用存储属性,因此这样做没有意义。

对于第(2)点,你必须强制进行向下转换,因为你试图访问一个属性 - 即y - 它不存在于超类中。如果要通过超类引用访问子类,则必须将自己限制为该超类提供的接口。 A没有y属性,因此当bar.y类型为bar时尝试访问A没有任何意义 - 你必须垂头丧气要输入B来执行此操作。

在OOP中,向上转换通常很容易,因为我们从继承结构中知道BA,因此以这种方式转换它很简单。但在相反的方向上却不是这样 - 当B继承自A时,BA,但A不是B。因此,当您从A向下转换为B时,您必须明确地执行此操作,因为如果要转换的内容根本不是B,则会发生错误的事情

顺便说一下,您不必强制使用as!向下投射 - 您可以使用as?安全地尝试投降

if let bar = mylist[2] as? B {
    print(bar.y)
}
else {
    print("not a B!")
}