Swift - 'internal' modifier cannot be used in protocols - swift

I am getting compiler error when I am declaring function internal inside Swift protocol,
protocol MyProtocol {
internal func test()
}
Error:
'internal' modifier cannot be used in protocols
Error is resolved if I remove the access modifier internal but I want to know why I am getting this error? As documentation mentioned default access level will be internal in case if I do not explicitly mention any access level. So why it is producing comilers error when I am making it explicit.

Please scroll down in the linked article
Protocols
If you want to assign an explicit access level to a protocol type, do so at the point that you define the protocol. This enables you to create protocols that can only be adopted within a certain access context.
The access level of each requirement within a protocol definition is automatically set to the same access level as the protocol. You can’t set a protocol requirement to a different access level than the protocol it supports. This ensures that all of the protocol’s requirements will be visible on any type that adopts the protocol.
It means you have to declare
internal protocol MyProtocol {
func test()
}

Related

How to create a Protocol in a Package without requiring Variables to be implemented Public?

Context
I have a Protocol, let's name it Entity, defined in a Swift Package. Since I want to use it in my projects, I set the Access Level to Public. However, Xcode is forcing me to set all Variables and Methods to Public as well, that were specified in the Protocol.
Compiler Error: Property 'name' must be declared public because it matches a requirement in public protocol 'Entity'
Code
// Swift Package
public protocol Entity {
static var name: String
}
// Project
extension SomeEntity: Entity { // Compiler Error
static var name: String = "Some Entity"
}
Question
How can I declare a Protocol in a Swift Package without requiring all Requirements to be made Public as well?
You cannot do that.
If you make a type conform to a protocol, the conform will have the same access identifiers as the type itself. So if you make a public type conform to a protocol, the protocol conformance will be public as well.
In order for a type to conform to a protocol, all protocol requirements must be met. And if you are able to refer to a type as the protocol it conforms to, you must be able to access all protocol requirements as well.
So if you declare a type public and make it conform to a protocol, you must declare all protocol requirements (both properties and methods) as public.
This is by design and you cannot get around it.

How to make protocol exportable from a swift library without making it public?

in my swift library I have a simple protocol like this:
protocol DebugPrintable {
func debug() -> String
}
I would like to export it so that users of the library can refer to the protocol, but that would turn it into a public protocol:
public protocol DebugPrintable {
func debug() -> String
}
... which forces all uses of protocol to be public - which is unnecessary.
Can I somehow make the protocol public (so that it is exported from library) but not make it force all declared properties to be public?
Here from documentation
You can’t set a protocol requirement to a different access level than
the protocol it supports. This ensures that all of the protocol’s
requirements will be visible on any type that adopts the protocol.
If you define a public protocol, the protocol’s requirements require a public access level for those requirements when they’re implemented. This behavior is different from other types, where a public type definition implies an access level of internal for the type’s members.
https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html
I think you should move your protected properties to another protocol to satisfy above thing.

Swift: Protocol With associatedType

I have a question about Protocol with associated type, why I can not make the protocol a type of my instance for example:
I know I can use Type Erasure to fix the issue, but why protocol with an associated type does not like to be a type of an instance, and if you will say because the associated type is also used as a constraint, well I want to implement the properties inside the protocol not inside its extensions since protocol extensions has the power to control who can access its properties, why we still have this issue.
Thank you.
There are lots of articles and answers (like this one) out there describing why but in summary, It needs associatedtype. Variables can not have an associatedtype. So alongside with Type Erasure method (that you don't want), you can simply make it opaque with adding some keyword to the type:
var objectA: some ProtocolA = A()

Why can't extensions with protocol conformances have a specific access level?

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.
Question
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?
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 I obey the compiler and remove the private/public designation, what is the access level of someFunction()?
Whatever you say it is. Nothing stops you from marking the access level of someFunction(). But in this case you cannot mark it as private, because the access level of MyProtocol is internal.
The default, therefore, is internal in your code. Nothing is ever public by default; public is always an explicitly opt-in designation.

access control on protocol implementation init

Trying to enforce an access control for a protocol that will be implemented by a singleton class.
I would like the class to have a fileprivate init, is there a way to enforce this behaviour?
Since a protocol is not a class i cannot put the init in the protocol extension.
According to Apple docs:
The access level of each requirement within a protocol definition is automatically set to the same access level as the protocol. You cannot set a protocol requirement to a different access level than the protocol it supports. This ensures that all of the protocol’s requirements will be visible on any type that adopts the protocol.
Link Protocol docs
EDIT: I have misread the question a bit.
If I understood OP's clarification, the only way I know at the moment to ensure that class is singleton is to mark its init method as private or fileprivate.
For my simple singleton with only static methods I have this:
private init() {
}