将类型超类赋给类型为子类

时间:2017-05-16 20:43:33

标签: swift inheritance subclass

我只是在学习编程并试图抓住继承的概念。

我有一个超类书:

class Book {
   var author : String
}

和子类:

class Comic : Book {
   var illustrator : String
}

我现在有一个函数可以在另一个类中返回一个Book

func someFunction() -> Book {
...
}

我认为这是可能的:

var someComic : Comic
someComic = someFunction()
someComic.illustrator = "John"

因为漫画是Book的子类,所以我应该能够为漫画分配一本书? (漫画继承了书中的al vars)但斯威夫特要我演员:

someComic = someFunction() as! Comic

然后在运行时崩溃......

以下是对亚历山大答案

的回复

假设Book有3个属性,Comic有2个额外属性(这比上面的例子更像真实情况)。 我漫画中需要的2个属性是根据Book中属性的值从外部源获取的。

    let books = someFunction()
    var comics = [Comic]()
    for book in books {
       let comicProperty1 = getComicProperty(book.propertyA)
       let comicProperty2 = getOtherComicProperty(book.propertyB)
       let comic = Comic (book.propertyA, book.propertyB, book.propertyC,comicProperty1,comicProperty2)
       comics.append(comic)
}

2 个答案:

答案 0 :(得分:2)

  

ComicBook的子类,因此我应该可以将Book分配给Comic

不,反过来说:您可以将Comic类型的对象分配给Book类型的变量,因为每个Comic都是Book。禁止将Book分配给Comic,因为并非每个Book都是Comic

  

Swift希望我在演出时投射然后崩溃。

那是因为someFunction会返回一个 Book的{​​{1}}对象。函数签名允许它返回任何类型的Comic,因此编译器无法捕获错误。因此,您在运行时获得异常。

答案 1 :(得分:0)

根据您对this answer的评论中提供的信息,我现在可以提供答案。你正在寻找的东西完全不能通过施展来实现。

如果您已有补充数据

假设您有一些书籍,例如您可能从someFunction获得的书籍:

let books = [book1, book2, book3]

假设您想要使用一些补充数据将您的图书变成漫画:

struct ComicSupplementalData {
    let illustrator: illustrator
    // Add other fields, if needed
}

let supplimentalData = [
    ComicSupplementalData(illustrator: "A"),
    ComicSupplementalData(illustrator: "B"),
    ComicSupplementalData(illustrator: "C")
]

您可以在Book上制作一个扩展程序,在Comic

的情况下将其提升为ComicSupplementalData
extension Book {
    func promoteToComic(_ supplemental: ComicSupplementalData) -> Comic {
        return Comic(
            author: self. author,
            illustrator: supplemental. illustrator
            // Add other fields, if needed
        )
    }
}

然后你可以将你的Book转换为Comic s(注意:此过程与投射完全无关):

let comics = zip(books, supplimentalData).map{ $0.promoteToComic($1) }

如果您需要获取补充数据

只需使用地图:

let books = someFunction()
let comics = books.map { book in
   return Comic(
       book.propertyA, book.propertyB, book.propertyC,
       getComicProperty(book.propertyA),
       getOtherComicProperty(book.propertyB)
   )
}