ios - 无法将“A”类型的值转换为“B”
问题描述
所以我试图解决我在另一个问题中描述的问题(致命错误:使用未实现的初始化程序 'init(...)' for class '__lldb_expr_1.B'),但后来我遇到了另一个问题。
我创建了一个测试项目来隔离问题。我有一个A.swift
包含以下内容的文件:
class A {
private let i: Int
private init(i: Int) {
self.i = i
}
}
extension A {
convenience init() {
self.init(i: 0)
}
}
然后在另一个文件中我声明B
为A
.
class B: A { }
为了测试这一点,我有一个简单ViewController
的这样的:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let b: B = B()
let a: A = b
_ = a as! B
}
}
这编译得很好,但是当我运行它时,它在向下转换a
为B
. 这是我得到的错误:
Could not cast value of type 'MyTestProject.A' (0x1070bd570) to
'MyTestProject.B' (0x1070bd4d8).
编辑:如果我在单独的文件中声明 A 和 B,我只会收到此错误。如果它们在同一个文件中声明,我会收到致命错误中描述的错误:使用未实现的初始化程序 'init(...)' for class '__lldb_expr_1.B'。
解决方案
这当然是一个错误。确定错误是什么并不容易。
作为我的测试,我稍微修改了你的例子。在这个文件中,我们有:
class A {
private let i: Int
private init(i: Int) {
self.i = i
}
convenience init() {
self.init(i: 0)
}
}
在我们的viewDidLoad
:
let a: A = B()
print(type(of:a))
这让事情变得简单而美好。好的,所以在另一个文件中,我们有
class B : A {}
那么,在我的测试中:
在发布版本中,我们崩溃了:“使用未实现的初始化程序 'init(i:)' 用于类 'B'”(我相信你认识那个)
在 Debug 构建中,我们不会崩溃,但会打印 A,这显然是错误的答案。
我可以添加复杂性(我尝试了很多东西),但我会添加以下观察:如果我们删除private
之前的单词,所有问题都会消失init
。通过这一更改,我们在 Debug 或 Release 中打印 B 并且不会崩溃。
所以我将推论这个问题与初始化器继承规则在底层实现的方式有关。它们似乎有能力在某些条件下打破多态性。(我的测试使用了 Xcode 11 beta 2,因此使用了 Swift 5.1。)
推荐阅读
- java - 如何避免多个 Switch case 语句
- javascript - 如何使用 auth().createUserWithEmailAndPassword 接收用户名和国家/地区
- javascript - 我无法从服务器获得响应
- autodesk-forge - 未从 Autodesk Forge API 收到 Webhook 事件
- uipath-robot - 协调器中的 Uipath 机器人调度
- html - 如何将页面导航到不同语言的 ID?
- android - Mapbox 反向地理编码并不总是返回结果
- java - 如何在java中输入并打印整个字符串?
- c++ - 如何将 GDI 位图转换为 GDI+ 位图、DrawImage?
- shell - 无法在 Jenkins 管道中执行“sh”命令