为什么具有协议一致性的扩展不能具有特定的访问级别?
Why can't extensions with protocol conformances have a specific access level?
假设我们有以下示例代码:
protocol MyProtocol {
func someFunction()
}
public class MyClass {
}
public extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
编译上面的代码出现以下错误:
Error: 'public' modifier cannot be used with extensions that declare protocol conformances
如果我将扩展名标记为 private
,同样的事情也会发生。似乎您无法设置符合协议的扩展的访问级别,无论访问级别设置为什么。即使将协议声明设置为 public
或 private
也不会消除错误。
问题
如果扩展符合协议,Swift 以这种方式限制扩展访问级别的原因是什么?如果在class级别应用协议一致性,则没有这样的限制。
如果我服从编译器并删除 private
/public
指定,someFunction()
的访问级别是多少?
extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
我想在这种情况下它会遵循最初的 MyClass
实现并且是 public
但我不确定。
出现这种行为是因为扩展中的协议一致性意味着整个 class 都符合该协议,因此在扩展中重新指定访问级别是多余的吗?
If I obey the compiler and remove the private/public designation, what is the access level of someFunction()?
随便你怎么说。没有什么能阻止您标记 someFunction()
的访问级别。但是在这种情况下你不能把它标记为private
,因为MyProtocol的访问级别是internal
.
因此,您的代码中的默认值为 internal
。默认情况下没有 public
; public
始终是明确选择加入的指定。
这是因为除了协议本身的访问级别之外,不可能在任何访问级别上遵守协议。换句话说,如果你有一个 public
协议,你就不能 private
遵守它。这部分是因为协议一致性是可以在运行时查询的东西(因此不能在你所在的模块之间有所不同,或者在不同的 files/modules 中实现两次),部分是因为它很奇怪如果一种类型符合一个文件中的协议,但在其他文件中使用时不符合该协议。
至于您关于 someFunction
的访问级别的问题,它遵循与任何其他功能相同的规则。也就是说,它默认为 internal
,除非该类型本身具有较低的访问级别。所以在你的情况下,如果 MyClass
和 MyProtocol
都是 public
,你可能会得到一个编译器错误,告诉你 someFunction()
需要被标记为 public
以及。但由于看起来 MyProtocol
实际上是 internal
,因此省略任何访问修饰符都可以作为 someFunction()
默认为 internal
.
私有一致性可能违反里氏替换原则
引用 apple devloper 论坛对类似问题的回复摘要:
"The biggest thing I've noted about private conformance, especially amonst classes that are meant to be subclassed further, is that you often end up with conflicting implementations."
例如,您有一个 class 私下遵守协议并实现其所有方法。后来出现了一个 subclass 并想做同样的事情,但只想实现所需的方法(因为未实现的可选方法可能会提供 subclass 想要的一些默认行为)。但是现在你有两个问题:
1) 期望此协议实现的对象现在可能在同一对象上有 2 个协议使用者。这导致两个对象都必须防止意外调用。或none,由于私有一致性,subclass无法调用super来解决意外调用。
2) subclass 无法在不修改协议的情况下获得它想要的行为,因为 superclass 的实现不能在不影响其行为的情况下被删除要么。
假设我们有以下示例代码:
protocol MyProtocol {
func someFunction()
}
public class MyClass {
}
public extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
编译上面的代码出现以下错误:
Error: 'public' modifier cannot be used with extensions that declare protocol conformances
如果我将扩展名标记为 private
,同样的事情也会发生。似乎您无法设置符合协议的扩展的访问级别,无论访问级别设置为什么。即使将协议声明设置为 public
或 private
也不会消除错误。
问题
如果扩展符合协议,Swift 以这种方式限制扩展访问级别的原因是什么?如果在class级别应用协议一致性,则没有这样的限制。
如果我服从编译器并删除 private
/public
指定,someFunction()
的访问级别是多少?
extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
我想在这种情况下它会遵循最初的 MyClass
实现并且是 public
但我不确定。
出现这种行为是因为扩展中的协议一致性意味着整个 class 都符合该协议,因此在扩展中重新指定访问级别是多余的吗?
If I obey the compiler and remove the private/public designation, what is the access level of
someFunction()?
随便你怎么说。没有什么能阻止您标记 someFunction()
的访问级别。但是在这种情况下你不能把它标记为private
,因为MyProtocol的访问级别是internal
.
因此,您的代码中的默认值为 internal
。默认情况下没有 public
; public
始终是明确选择加入的指定。
这是因为除了协议本身的访问级别之外,不可能在任何访问级别上遵守协议。换句话说,如果你有一个 public
协议,你就不能 private
遵守它。这部分是因为协议一致性是可以在运行时查询的东西(因此不能在你所在的模块之间有所不同,或者在不同的 files/modules 中实现两次),部分是因为它很奇怪如果一种类型符合一个文件中的协议,但在其他文件中使用时不符合该协议。
至于您关于 someFunction
的访问级别的问题,它遵循与任何其他功能相同的规则。也就是说,它默认为 internal
,除非该类型本身具有较低的访问级别。所以在你的情况下,如果 MyClass
和 MyProtocol
都是 public
,你可能会得到一个编译器错误,告诉你 someFunction()
需要被标记为 public
以及。但由于看起来 MyProtocol
实际上是 internal
,因此省略任何访问修饰符都可以作为 someFunction()
默认为 internal
.
私有一致性可能违反里氏替换原则
引用 apple devloper 论坛对类似问题的回复摘要:
"The biggest thing I've noted about private conformance, especially amonst classes that are meant to be subclassed further, is that you often end up with conflicting implementations."
例如,您有一个 class 私下遵守协议并实现其所有方法。后来出现了一个 subclass 并想做同样的事情,但只想实现所需的方法(因为未实现的可选方法可能会提供 subclass 想要的一些默认行为)。但是现在你有两个问题:
1) 期望此协议实现的对象现在可能在同一对象上有 2 个协议使用者。这导致两个对象都必须防止意外调用。或none,由于私有一致性,subclass无法调用super来解决意外调用。
2) subclass 无法在不修改协议的情况下获得它想要的行为,因为 superclass 的实现不能在不影响其行为的情况下被删除要么。