Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to declare protocol property as private?

I want to conform to a protocol, as well as to hide its conformed properties to be accessed (declare them as private).

Consider the following:

protocol P {
    var value: String { get }

    init(value: String)
}

class C: P {
    var value: String

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

I would create a C object:

let myObject = C(value: "Hello World")
myObject.value = "New Value"

Based on that I have 2 questions:

Now, if I tried to declare value as private:

private var value: String { get }

the compiler will throw an error:

'private' modifier cannot be used in protocols

with a fix suggestion to replace the private with internal.

How can I prevent value from being accessible by saying myObject.value? if there is no way, what's the reason of this limitation?

like image 585
Ahmad F Avatar asked Jul 12 '18 12:07

Ahmad F


People also ask

CAN protocol be file private?

Yes this is exactly the use case. A workaround is to have a function accept all the properties which were private inside the Protocol, and have a protocol extension implement the function.

CAN protocol have stored property?

A protocol can require any conforming type to provide an instance property or type property with a particular name and type. The protocol doesn't specify whether the property should be a stored property or a computed property—it only specifies the required property name and type.

Can a protocol inherit another protocol?

One protocol can inherit from another in a process known as protocol inheritance. Unlike with classes, you can inherit from multiple protocols at the same time before you add your own customizations on top. Now we can make new types conform to that single protocol rather than each of the three individual ones.


1 Answers

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
like image 183
Martin R Avatar answered Sep 19 '22 11:09

Martin R