快速访问控制4
从
Swift3升级到
Swift4时,我遇到了一些与访问控制有关的问题.
这是示例代码. Swift3中有哪些,过去工作正常 – open class MyClass { private let value: Int static var defaultValue: Int { return 10 } public init(value: Int = MyClass.defaultValue) { self.value = value } } 为了使代码在Swift4中运行,我必须将defaultValue的访问控制更改为public. open class MyClass { private let value: Int static public var defaultValue: Int { return 10 } public init(value: Int = MyClass.defaultValue) { self.value = value } } 当我想知道发生了什么时,我试图删除MyClass的开放访问控制,它允许我删除defaultValue的访问标识符.甚至可以把它私有化. class MyClass { private let value: Int private static var defaultValue: Int { return 10 } public init(value: Int = MyClass.defaultValue) { self.value = value } } 我理解所有访问标识符,但我无法理解这种行为.特别是第一种情况,xcode强迫我将defaultValue的访问控制权改为public. 请帮忙. 解决方法
我的原始答案(如下所示)现在已经过时了 – 弹性模型
are to be implemented in Swift 4.2的开头,引入了@inlinable和@usableFromInline属性,对应于旧的@_inlineable和@_versioned属性.
此外,更重要的是,公共可访问函数的默认参数可以引用的规则再次发生了变化.要回顾以前的规则: >在Swift 3中,没有强制执行这样的默认参数表达式可以引用的访问级别(允许你的第一个例子,其中defaultValue是内部的). 但是在Swift 4.2中,随着SE-0193,the rule is now的实现,公共可访问函数的默认参数表达式只能引用可公开访问的声明(甚至不是@inlinable internal或@usableFromInline internal). 我相信这为在模块生成的接口文件中显示默认参数表达式铺平了道路.目前Swift只显示了一个无用的=默认值,但我相信这会改变为实际显示默认参数.这只能通过适当的新访问控制限制实际发生(编辑:这是now happening). 老答案(斯威夫特4) 这种变化是由于已经通过强调属性(@_ inlineable,@ _ version,@ _ fixed_layout)提供的弹性模型的工作,但还没有正式确定(所以你可能不应该自己使用这些属性) .您可以阅读有关full proposed details of the resilience model here以及Swift evolution discussion on it here的信息. 简而言之,可内联函数的实现和声明作为模块接口的一部分公开,因此可以在从另一个模块调用时进行内联.因此,一个可内联的函数也必须首先公开访问(即公共或更高版本). 您遇到的是default argument expressions for publically accessible functions inlineable的更改,这意味着它们必须可以直接在调用模块的二进制文件中进行评估.这减少了使用来自另一个模块的默认参数值调用函数的开销,因为编译器不再需要为每个默认参数执行函数调用.它已经知道了实施. 我不相信Swift 4本身的发布中正式记录了这一变化,但是Swift编译工程师Slava Pestov确认了这一点,who says:
因此,如果您有一个具有默认参数表达式的公共可访问函数(例如,在您的情况下为MyClass.defaultValue),则该表达式现在只能引用也是该模块接口的一部分的内容.因此,您需要公开访问defaultValue. 不幸的是,目前无法将私有函数的声明作为模块接口的一部分(这将允许您在默认参数表达式中使用它).促进此操作的属性是@_versioned,但由于以下原因,它被禁止(文件)私有given by Slava Pestov:
您可以使用@_versioned var defaultValue实现此目的: open class MyClass { private let value: Int @_versioned static var defaultValue: Int { return 10 } public init(value: Int = MyClass.defaultValue) { self.value = value } } MyClass.defaultValue的声明现在作为模块接口的一部分导出,但仍然无法从另一个模块的代码中直接调用(因为它是内部的).但是,该模块的编译器现在可以在评估默认参数表达式时调用它.但是,如前所述,您可能不应该在此处使用下划线属性;你应该等到弹性模型最终确定. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |