Assume we have the following example code:
protocol MyProtocol { func someFunction() } public class MyClass { } public extension MyClass: MyProtocol { func someFunction() { print("hello") } }
Compiling the code above gives the following error:
Error: 'public' modifier cannot be used with extensions that declare protocol conformances
The same thing occurs if I mark the extension as private
. It seems as though you cannot set the access level of an extension that conforms to a protocol, regardless of what the access level is set to. Even setting the protocol declaration to public
or private
does not remove the error.
What is the reasoning for Swift restricting an extension's access level in this way if it conforms to a protocol? If the protocol conformance is applied at the class level, there is no such restriction.
If I obey the compiler and remove the private
/public
designation, what is the access level of someFunction()
?
extension MyClass: MyProtocol { func someFunction() { print("hello") } }
I imagine in this case it would follow the original MyClass
implementation and be public
but I am not sure.
Is this behavior there because a protocol conformance in an extension means the entire class conforms to the protocol, and therefore it is redundant to re-specify the access level in the extension?
A protocol defines a blueprint of methods, properties, and other requirements. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. But there would be a time when you want to restrict protocols to be adopted by a specific class.
Protocols let you describe what methods something should have, but don't provide the code inside. Extensions let you provide the code inside your methods, but only affect one data type – you can't add the method to lots of types at the same time.
Protocol ConformanceSwift classes, structures, and enumerations can all conform to protocols. The syntax for conforming to a protocol is to add the protocol name after the type name, separated by a colon. A type can declare conformance to multiple protocols by listing the protocol names separated by commas.
Protocol InheritanceSwift 4 allows protocols to inherit properties from its defined properties. It is similar to that of class inheritance, but with the choice of listing multiple inherited protocols separated by commas.
It's because it's impossible to conform to a protocol at any access level other than the access level of the protocol itself. In other words, if you have a public
protocol, you cannot have private
conformance to it. This is partially because protocol conformance is something that can be queried for at runtime (and therefore cannot differ between what module you're in, or be implemented twice in different files/modules), and partially because it would just plain be weird if a type conformed to a protocol in one file and didn't conform to that protocol when used in other files.
As for your question of the access level of someFunction
, it follows the same rules as any other function. Which is to say, it defaults to internal
, unless the type itself has a lower access level. So in your case, if MyClass
and MyProtocol
are both public
, you can expect to get a compiler error telling you that someFunction()
needs to be marked public
as well. But since it looks like MyProtocol
is in fact internal
, omitting any access modifier works as someFunction()
defaults to internal
.
Private conformance might violate Liskov Substitution Principle
Quoting an abstract from apple devloper forum reply to a similar question:
"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."
For example, you have a class that privately conforms to a protocol and implements all of its methods. Later a subclass comes along and wants to do the same, but only wants to implement the required methods (because the optional ones not being implemented might provide some default behavior that subclass wants). But now you have 2 problems:
1) The object expecting this protocol implementation now has possibly 2 consumers of the protocol on the same object. This leads to both objects having to guard against unexpected calls. Or none, as due to the private conformance, the subclass can't call super to resolve the unexpected calls.
2) There is no way for the subclass to get the behavior it wants without modifying the protocol, as the superclass's implementation can't be removed without affecting its behavior either.
Source: Link to Apple Developer forum thread
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With