为什么我必须强制将数组对象向下转换为swift中的子类

为什么我必须强制将数组对象向下转换为swift中的子类,swift,Swift,我有以下——简化的——代码: 在swift 2.1中,我必须使用as!或者我得到一条错误消息,A不能转换为B。我应该强制转换到子类,这似乎是错误的,但也许我遗漏了什么 注释掉的部分是我的第一次尝试,但它也不能用类型为“[B]”的消息myList编译,不能重写类型为“[a]”的属性 在这两种情况下,我都不理解这种行为,因为B显然是a的一个子类 有人能解释为什么我不能推翻声明吗 有人能解释一下我为什么要强迫他们失望吗 谢谢 对于点(1),您根本无法覆盖存储的属性,只能覆盖计算的属性。此外,即使重写计

我有以下——简化的——代码:

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

注释掉的部分是我的第一次尝试,但它也不能用类型为“[B]”的消息myList编译,不能重写类型为“[a]”的属性

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

  • 有人能解释为什么我不能推翻声明吗
  • 有人能解释一下我为什么要强迫他们失望吗
  • 谢谢

    对于点(1),您根本无法覆盖存储的属性,只能覆盖计算的属性。此外,即使重写计算属性,也不能像这里尝试的那样为其指定不同的类型。由于您无法更改类型,因此重写存储的属性实际上毫无意义—您会将其重写为什么?如果它是超类中的
    int
    和子类中的
    int
    ,或者是超类中的
    [A]
    和子类中的
    [A]
    ,那么您实际上没有通过重写它来更改任何内容。您可以通过重写计算属性来更改行为,但显然不能使用存储属性,因此这样做没有什么意义

    对于第(2)点,您必须强制向下转换,因为您试图访问超类中不存在的属性,即
    y
    。如果希望通过超类引用访问子类,则必须将自己限制为该超类提供的接口
    A
    没有
    y
    属性,因此当
    bar
    A
    类型时,尝试访问
    bar.y
    没有意义-必须将其向下转换为
    B
    类型才能执行此操作

    在OOP中,向上转换通常很容易,因为我们从继承结构中知道,
    B
    是一个
    A
    ,所以用这种方式转换很简单。但相反的方向,情况并非如此——当
    B
    继承自
    A
    时,A
    B
    就是
    A
    ,但
    A
    不是
    B
    。因此,当你从
    A
    向下转换为
    B
    时,你必须明确地这样做,因为如果你转换的东西根本不是A
    B
    ,就会发生坏事

    顺便说一句,您不必使用
    as强制向下播放-您可以使用
    作为?
    安全地进行尝试,例如:

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

    编译器如何知道
    myList
    包含
    B
    ?在几乎任何语言中,您都必须显式地向下转换(转换为子类)。在java或C++中也是这样。我明白你必须明确地下注,这不是我的问题。我的问题是为什么我必须添加!强制向下播放。错误不是在访问y时发生的。错误在编译器让我在!对于as,这似乎有点过分,因为B是a的子类,myList被声明为a的数组。
    if let bar = mylist[2] as? B {
        print(bar.y)
    }
    else {
        print("not a B!")
    }