How to Declare Protocol Property as Private

Is there a way to declare protocol property as private?

Conforming to

protocol P {
var value: String { get }

init(value: String)
}

requires a gettable property value with default access. If write access to the
property in the conforming class should be restricted to the class itself
then you can declare it as in Swift readonly external, readwrite internal property:

class C: P {
private(set) var value: String

required init(value: String) {
self.value = value
}
}

let myObject = C(value: "Hello World")
print(myObject.value) // OK
myObject.value = "New Value" // Error: Cannot assign to property: 'value' setter is inaccessible

And if the property should only be set in initializers then make it
a constant:

class C: P {
let value: String

required init(value: String) {
self.value = value
}
}

let myObject = C(value: "Hello World")
print(myObject.value) // OK
myObject.value = "New Value" // Error: Cannot assign to property: 'value' is a 'let' constant

Swift. Declaring private functions in internal protocol

From Apple's docs it looks like the only way to achieve what you are trying to do is to implement 2 protocols - one internal, and one private, as Apple states "You cannot set a protocol requirement to a different access level than the protocol it supports."

Implement a public method that rely on a private property in Swift using protocols

Following this discussion from Swift forum, there are two ways to solve the issue.

First one is straightforward:

/// The publically visible capabilities.
public protocol SameModifierProtocol {
func modifier(x: Int) -> SameModifierProtocol
}
/// The internal requirements on which the default implementation relies.
internal protocol SynthesizedSameModifierProtocolConformance:
SameModifierProtocol {
var x: Int { get set }
}
/// The default implementation.
extension SynthesizedSameModifierProtocolConformance {
public func modifier(x: Int) -> SameModifierProtocol{
var s = self
s.x = x
return s
}
}

/// Conforms to the public protocol
/// and requests the default implementation from the internal one.
/// Clients can only see the public protocol.
public struct Component: SynthesizedSameModifierProtocolConformance {
internal var x: Int = 0
public init() {}
}

The second involves an unofficial feature @_spi, that allows to make implementation details unexposed in a public protocol:

public protocol SameModifierProtocol {
@_spi(SameModifier) var x: Int { get set }
}

extension SameModifierProtocol {
public func modifier(x: Int) -> Self {
var s = self
s.x = x
return s
}
}

public struct Component: SameModifierProtocol {
@_spi(SameModifier) public var x: Int = 0
public init() {}
}

Swift protocol property of type SetSelf

The way to put constraints in protocols is similar to how you specify protocol conformance (they're the same thing after all)

protocol Groupable: Hashable
{
var parent: Self? { get }
var children: Set<Self> { get }
}

swift protocol conformance when same property name is optional

There is no elegant solution to your problem other than renaming the conflicting property on the conforming type.

Swift doesn't allow 2 properties of the same name to exist on a type even if their types are different. On the other hand, Int? and Int are completely different types, so you cannot have trackNumber: Int fulfil the protocol requirement of trackNumber: Int?.

The only solution (other than changing the type in either the protocol or the struct) is to rename the non-Optional property in SpotifyTrack and make an optional computed property of the same name returning the non-optional one.

protocol Track {
var trackNumber: Int? { get }
}
struct SpotifyTrack {
private let _trackNumber: Int
}
extension SpotifyTrack: Track {
var trackNumber: Int? { _trackNumber }
}


Related Topics



Leave a reply



Submit