我知道通过在Swift中使属性和方法最终,我可以改善编译时间和应用程序的性能。最近我读了Apple博客文章:https://developer.apple.com/swift/blog/?id=27,其中声明将财产或方法(文件)设为私有(博客文章的历史可以追溯到2015年,当时#34;私有"意味着" fileprivate")使编译器能够推断出" finality"属性或方法,通过在源文件中搜索任何覆盖。但是"真实" (斯威夫特3)私人?编译器不应该在任何地方搜索潜在的覆盖,所以我的问题是:
这两个声明之间是否有任何性能和/或编译时间差异?
private final var foo: Int
private var bar: Int
答案 0 :(得分:2)
标记为private
的方法或属性隐含final
。
在@conarch提供的测试中,有一个副作用 - 调度类。
我做了与休闲相同的测试:
class UseFinal {
private final var foo = 1
}
class NoUseFinal {
private var foo = 1
}
var start = Date()
print(NoUseFinal())
print(UseFinal())
print("construct takes \(Date().timeIntervalSince(start))")
start = Date()
for _ in 1...1_000_000 {
let temp = NoUseFinal()
}
print("noUseFinal took \(Date().timeIntervalSince(start))")
start = Date()
for _ in 1...1_000_000 {
let temp = UseFinal()
}
print("useFinal took \(Date().timeIntervalSince(start))")
print("----")
start = Date()
for _ in 1...1_000_000 {
let temp = UseFinal()
}
print("useFinal took \(Date().timeIntervalSince(start))")
start = Date()
for _ in 1...1_000_000 {
let temp = NoUseFinal()
}
print("noUseFinal took \(Date().timeIntervalSince(start))")
我得到的结果如下:
NoUseFinal
UseFinal
----
construct takes 0.000900983810424805
noUseFinal took 0.182932019233704
useFinal took 0.182898044586182
----
useFinal took 0.183371007442474
noUseFinal took 0.182500004768372
因此调度程序的private
和private final
方法或属性之间没有区别
答案 1 :(得分:1)
我做了两个简单的课程:
class UseFinal
{
private final var foo = 1
}
class NoUseFinal
{
private var foo = 1
}
并运行以下代码:
var start = Date()
for _ in 1...100000
{
let temp = NoUseFinal()
}
print("noUseFinal took \(Date().timeIntervalSince(start))")
start = Date()
for _ in 1...100000
{
let temp = UseFinal()
}
print("useFinal took \(Date().timeIntervalSince(start))")
结果一致表明,添加“最终”显然更快。一个示例输出:
noUseFinal took 0.0214230418205261
useFinal took 0.0155709981918335
修改强>
出于好奇,并且由于之前的拼写错误,我尝试切换for循环的顺序,以便首先命中UseFinal类。这导致THAT类成为花费更长时间的类:即时间几乎与另一个运行相同,除了现在UseFinal花费的时间更长。这让我现在相信......没有区别。我认为它们归结为当天结束时的完全相同的位。
答案 2 :(得分:0)
final
用于在运行时减少动态调度。这样性能会更好。
用于可见性的程序必须在运行时确定哪种方法或peroperty 被引用,然后进行间接呼叫或间接访问。 这种技术称为动态调度。
private
关键字。当您使用private
时,如果编译器发现没有被覆盖的声明,则编译器将在前面推断出final
关键字,然后所有呼叫变为直接。性能也得到了提高。但应该不如final
那么好。
答案 3 :(得分:0)
不一定适用于 func/vars,但如果我有一个文件,并且在该文件中我有一个 private
类,我不想在同一个文件中继承该类,我必须将该类标记为 {{ 1}}。