问题
- 我知道我可能不应该摆弄内置类型,但我很好奇,
Builtin.Int1
类型真的应该像下面这样公开访问吗?如果是这样的话,为什么将它用作数组元素会导致Swift崩溃
我很好奇,因为我从来没有遇到过我自己无法存储在数组中的自定义类型(但我想内置类型与我可以使用"public Swift"构建的类型不同)。
我使用的是Swift 2.2和Xcode 7.3。
详细信息
查看swift/stdlib/public/core/Bol.swift的源代码,我们注意到,我们可以隐式地访问内部类型Builtin.Int1
(1位整数),它构成swift中Bool
类型的基础。
public struct Bool { internal var _value: Builtin.Int1 // ... } extension Bool : Boolean { // ... public func _getBuiltinLogicValue() -> Builtin.Int1 { return _value } // ... }
因此,使用_getBuiltinLogicValue()
,我们可以构造Builtin.Int1
类型的值,并使用它声明[Builtin.Int1]
类型的空数组。
/* public access to _getBuiltinLogicValue() ... */
let bar = false._getBuiltinLogicValue()
print(bar.dynamicType)
/* '<<<opaque type>>>' */
/* Alt-click: 'Int1' type */
print(_getBool(bar)) // false, OK
/* construct an empty array of 'Int1':s */
func foo<T>(val: T, arr: [T] = []) -> [T] {
return arr
}
var arr = foo(bar)
print(arr.dynamicType)
/* 'Array<<<<opaque type>>>>' */
/* Alt-click: '[Int1]' type */
然而,如果我们试图将任何Builtint.Int1
元素添加到这个数组中,Swift就会崩溃(运行时异常)
/* however any attempt to fill such an array (or initialize
one as none-empty) will yield a runtime exception */
//arr.append(bar) // runtime error
//let arr2 = [bar] // runtime error
执行中断,原因:EXC_BAD_ACCESS(代码=1,地址=0x10)
我最后注意到,在源swift/stdlib/public/core/Builtin.swift中,
// Definitions that make elements of Builtin usable in real code // without gobs of boilerplate.
这可能表明我们应该能够使用上面的内置类型。
调用带前导下划线的方法时,就不再调用公共方法。它有一个public
属性的事实通常是由于语言限制,要求它是这样的。将其与_ArrayType
进行比较,后者在技术上也是public
,但这只是因为Swift无法隐藏实现细节。你仍然不应该直接使用它。他们强调这些事情是有原因的。(我在自己的代码中遇到过这种情况。创建依赖非公共属性的协议扩展通常很困难或不可能;当你完成时,许多你想要成为private
或internal
的东西必须是public
,否则它就无法编译。)
你最初的断言"我可能不应该摆弄内置类型"在这个时候是正确的。在未来,可能会有更多的内置产品。但事实上,你必须欺骗编译器,甚至允许通过泛型实现这一点,这应该是你的问题的答案。不可以。您不应该期望能够以这种方式使用内置类型。