类型擦除:在擦除类型信息时,我们是否会冒不可逆转地失去对已擦除类型实例的保持活动数据的访问权限的风险?
Type erasure: do we risk non-reversibly losing access to kept-alive data of the instance of the erased type, when erasing the type information?
考虑以下常见的简单类型擦除方案
protocol Foo {
associatedtype Bar
func bar() -> Bar
}
struct AnyFoo<Bar>: Foo {
private let _bar: () -> Bar
init<F: Foo>(_ foo: F) where F.Bar == Bar {
_bar = foo.bar
/* stores a reference to foo.bar,
so foo kept alive by ARC? */
}
func bar() -> Bar {
return _bar()
}
}
假设上面的初始化参数 foo
是(打算是)"large" 类型的临时实例,我们只对从中切出 [=13 蓝图的信息感兴趣=](即 bar()
方法)。
struct Huge { /* ... */ }
struct Foobar: Foo {
internal func bar() -> String {
return "foo"
}
let lotsOfData: Huge = Huge()
}
func getAnyFooStr() -> AnyFoo<String> {
let foobar = Foobar()
return AnyFoo(foobar)
}
let anyStrFoo = getAnyFooStr()
/* we can now access anyStrFoo.bar() (-> "foo") from our
erased type, but do lotsOfData of the underlying seemingly
temporary Foobar() instance still "live", unreachable? */
- 问: 由于闭包是引用类型,我们是否仍会在内存中保留
foo
的剩余内容且无法访问?如果是这样,我想我们将永远无法收回对这些丢失但仍然存在的内容的访问权限?
(我尝试将 Foobar
作为 class,监控(缺少)deinit
调用,但我自己很困惑最后一个小时我需要一些非自我验证,特别是当 Foobar
是一个值类型的情况下)
Xcode 8.0 / Swift 3.
是的,它与类型擦除无关:)
闭包 Foobar().bar
保留它绑定的实例
(及其所有属性)只要闭包还活着就活着。
这是一个简化的例子:
class Huge {
deinit { print("deinit Huge") }
}
struct Foobar {
internal func bar() -> String {
return "foo"
}
let lotsOfData: Huge = Huge()
}
do {
let fb = Foobar().bar // the type of `fb` is `() -> String`
print("still alive ...")
}
print("... out of scope now")
输出:
still alive ...
deinit Huge
... out of scope now
考虑以下常见的简单类型擦除方案
protocol Foo {
associatedtype Bar
func bar() -> Bar
}
struct AnyFoo<Bar>: Foo {
private let _bar: () -> Bar
init<F: Foo>(_ foo: F) where F.Bar == Bar {
_bar = foo.bar
/* stores a reference to foo.bar,
so foo kept alive by ARC? */
}
func bar() -> Bar {
return _bar()
}
}
假设上面的初始化参数 foo
是(打算是)"large" 类型的临时实例,我们只对从中切出 [=13 蓝图的信息感兴趣=](即 bar()
方法)。
struct Huge { /* ... */ }
struct Foobar: Foo {
internal func bar() -> String {
return "foo"
}
let lotsOfData: Huge = Huge()
}
func getAnyFooStr() -> AnyFoo<String> {
let foobar = Foobar()
return AnyFoo(foobar)
}
let anyStrFoo = getAnyFooStr()
/* we can now access anyStrFoo.bar() (-> "foo") from our
erased type, but do lotsOfData of the underlying seemingly
temporary Foobar() instance still "live", unreachable? */
- 问: 由于闭包是引用类型,我们是否仍会在内存中保留
foo
的剩余内容且无法访问?如果是这样,我想我们将永远无法收回对这些丢失但仍然存在的内容的访问权限?
(我尝试将 Foobar
作为 class,监控(缺少)deinit
调用,但我自己很困惑最后一个小时我需要一些非自我验证,特别是当 Foobar
是一个值类型的情况下)
Xcode 8.0 / Swift 3.
是的,它与类型擦除无关:)
闭包 Foobar().bar
保留它绑定的实例
(及其所有属性)只要闭包还活着就活着。
这是一个简化的例子:
class Huge {
deinit { print("deinit Huge") }
}
struct Foobar {
internal func bar() -> String {
return "foo"
}
let lotsOfData: Huge = Huge()
}
do {
let fb = Foobar().bar // the type of `fb` is `() -> String`
print("still alive ...")
}
print("... out of scope now")
输出:
still alive ... deinit Huge ... out of scope now