我只是在学习编程并试图抓住继承的概念。
我有一个超类书:
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)
}
答案 0 :(得分:2)
Comic
是Book
的子类,因此我应该可以将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)
)
}