Internal Protocol Property

Hi


I've been trying to work around an issue whereby a have a public protocol with some public properties but also an internal one. For example:


public protocol ServiceTypeProtocol
{
    var type : String {get}
    var endpointUri: URL { get }
    var method: String { get }
}


And the implementation of the protocol would be somethig like this:


public struct Action : ServiceTypeProtocol {
    public var type: String
    public var endpointUri: URL
    internal var method: String

    init(_ type: String, endpointUri : String)
    {
        self.type = type
        self.endpointUri = endpointUri
        self.method = type == "cloud" ? "delete" : "patch"
    }
}


So method is only exposed internally from the Action struct. However the complier throws this error:

"Property 'method' must be declared public because it matches a requirement in public protocol 'ServiceTypeProtocol'"


If I change the protocol to the following, I end up with this error:
'internal' modifier cannot be used in protocols


public protocol ServiceTypeProtocol {
    var type : String {get}
    var endpointUri: URL { get }
    internal var method: String { get }
}


I removed the method from the protocol and the Action struct and created an extension of the protocol this this:

internal extension ServiceTypeProtocol {
    var method : String
}


But you end up with the error:

Extensions may not contain stored properties


Then I tried this as well, at least it did compile...

internal extension ServiceTypeProtocol {
    var method : String {
        get { return "foo" }
        set { self.method = newValue }
    }
}


But the set operation repeats itself unti this error occurs:

EXC_BAD_ACCESS (code=2, address=0x7ffeeb937ff8)


So what approach have others used to keep a property internal still getable and only setable in the init?


Many thanks

If

method
is in the
ServiceTypeProtocol
,
Action
must expose at least a getter for it. My understanding is that you want to avoid exposing the setter. Is that right? If so, you can use
private(set)
, as shown below.
public protocol ServiceTypeProtocol
{
    var type : String { get }
    var endpointUri: URL { get }
    var method: String { get }
}

public struct Action : ServiceTypeProtocol {
    public var type: String
    public var endpointUri: URL
    public private(set) var method: String

    init(_ type: String, endpointUri : URL)
    {
        self.type = type
        self.endpointUri = endpointUri
        self.method = type == "cloud" ? "delete" : "patch"
    }
}

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Eskimo


I want to hide both the getting and setter from being publically accessible and only have access to method property internally.


Thanks

You can't approach it this way, because your public protocol makes all of its requirements (including "method") visible publicly, and therefore accessible publicly. You cannot restrict access other than via visibility.


I think the correct solution in your case is to make this protocol internal (possibly under a different name), and declare a second, public protocol that your Action type also conforms to, that doesn't have the "method" requirement. Conformance to the internal protocol will provide conformance to the public protocol automatically.

Hey there


I had a bit of a rethink on this protocol based on yours and Quinn's response. The method property shouldn't really be part of the protocol or struct at all, notwithstanding the Swift language semantics. I've removed the following from the Action.init


self.method = type == "cloud" ? "delete" : "patch"


The method can be assigned in a function, for example:


func execute(_ action: Action) {
   let method = action.type == "cloud" ? "delete" : "patch"
   ...
}


Thanks for making me rethink the approach 🙂

Internal Protocol Property
 
 
Q