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() {
}
Related
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.
I've just learned about extensions and I was wondering, there was an example about extending a protocol. For example, let's say we have the protocol:
protocol CanFly {
func canFly()
}
which allows all the classes who can fly to basiclly to fly. Now lets say that we use extension to extend the protocol, and we do:
extension CanFly {
func canEat() {
print("I can eat")
}
}
What is the purpose of that if we can just add that func canEat to our protocol? More of those protocols are like an abstract struct so why would we add a func with a body to it?
just wanna say if I've made a mess im sorry for that lol, just want to clear out few things about extension <3
Per Swift documentation on Protocol Extensions:
Protocols can be extended to provide method, initializer, subscript,
and computed property implementations to conforming types. This allows
you to define behavior on protocols themselves, rather than in each
type’s individual conformance or in a global function.
This means you can run logic within the protocol extension function so you don't have to do it in each class that conforms to the protocol.
Personally, I also find extensions useful to extend the functionality of built-in classes like String or UIViewController since extensions can be called from anywhere in an app. I have some open-source extension snippets you can take a look at if you'd like.
Extending a protocol is just one of the possible use cases for extensions, really powerful and useful, but might be confusing at the start.
I suggest you looking through this article, as it dives deeper into more mundane, so to speak, ways to use it.
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()
}
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.
I've never worked with objective C but have a fair bit of experience with C++.
What exactly is the difference between a superclass and a protocol in objective C? I read that a protocol is essentially a pure virtual class, but is that it? Is a protocol simply a specific type of superclass?
A protocol is a contract a class is going to conform to. When a class conforms to a protocol it tells the compiler that it will implement all the methods and all the properties declared in the protocol.
In Objective-C the class additionally needs a superclass. In a lot of cases this is NSObject. The superclass implements already a lot of methods (like isEqual:). A protocol never implements any methods or defines any property.
A protocol tells which properties/operations a class must implement. A superclass implements them and you can add your own stuff on top.
A protocol defines a set of method definitions that a class or struct must implement, very much like a Java interface.
A superclass is the class from which a given class inherits its method definitions, the implementation for those methods, and the instance and class properties.