gpt4 book ai didi

swift - 在 super.init 调用之前初始化非可选属性而不重复代码

转载 作者:可可西里 更新时间:2023-11-01 00:55:28 24 4
gpt4 key购买 nike

我在 Swift 中最沮丧的情况之一是当我有一个这样的类时:

class A: NSObject {
var a: Int

override init() {
clear()
super.init()
}

func clear() {
a = 5
}
}

当然,这会导致多个编译器错误('self' used in method call 'clear' before 'super.init' call and Property 'self.a' not initialized at super .init 调用

更改构造函数行的顺序只会修复第一个错误:

override init() {
super.init()
clear()
}

通常,我最终会做两件事中的一件。第一个选项是使 a 成为一个隐式展开的可选,但我觉得这是一种糟糕的风格,因为 a 在构造函数之后永远不会是 nil返回:

var a: Int! = nil

第二个选项是在构造函数中复制我的 clear() 函数的功能:

override init() {
a = 5
super.init()
}

这对于这个简化的示例来说效果很好,但它会在更复杂的代码库中不必要地重复大量代码。

有没有一种方法可以在不复制我的clear 函数或使a 成为可选函数的情况下初始化a?如果没有,为什么不呢?!

最佳答案

这个特定案例中的“为什么不”非常简单。你写的内容让我可以这样写:

class B: A {
override func clear() {}
}

然后 a 不会被初始化。所以你写的东西永远不可能是合法的 Swift。

也就是说,还有一个更深层次的版本可能合法但不合法。如果您将类标记为 final 或者如果这是一个结构,那么编译器可能能够通过内联所有可能的方法调用来证明所有代码路径上的所有内容都已正确初始化,但编译器不会今天不要做所有这些;它太复杂了。编译器只是说“我的证明引擎不是那么强大,所以取消它。”

IMO,这里正确的解决方案是 ! 类型,但我不会添加 = nil。那是误导。我会这样写:

class A: NSObject {
var a: Int! // You don't have to assign `!` types; they're automatically nil

override init() {
super.init()
clear()
}

func clear() {
a = 5
}
}

这表示“我有责任确保 a 在使用前被设置。”这正是你在做什么。当我需要将自己作为代表传递时,我总是这样做。我希望编译器能够在每个方法调用中探索每条可能的代码路径,但现在并没有(考虑到它可能对编译时间造成的影响,也许我不希望那样)。

but I feel that this is terrible style because a will never be nil after the constructor returns

这正是 ! 类型的意义所在。当任何其他对象可以接触到它们时,它们应该永远为零。如果它可能是 nil,那么您不应该使用 !。我同意 !危险的(因为编译器不再帮助您),但它的风格不错。

IMO 唯一合理的方法是分配默认值。我当然不会使用实际值;那会邀请微妙的错误。我只会使用一些默认值来让事情到位。

class A: NSObject {
var a = Int.min // -1 might be reasonable. I just like it to be clearly wrong
override init() {
super.init()
clear()
}

func clear() {
a = 5
}
}

我不喜欢这种方法,尽管我在几个地方使用过它。我认为它不会为您提供任何安全性 !(它不会崩溃,但您几乎肯定会给您带来细微的行为错误,我宁愿崩溃)。这是程序员必须注意的地方,因为编译器的功能强大到足以证明一切都是正确的,! 的意义在于标记这些地方。

关于swift - 在 super.init 调用之前初始化非可选属性而不重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49839059/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com