Swift Protocol Get Only Settable

Swift Protocol get only settable?

As per the official documentation:

The getter and setter requirements can be satisfied by a conforming type in a variety of ways. If a property declaration includes both the get and set keywords, a conforming type can implement it with a stored variable property or a computed property that is both readable and writeable (that is, one that implements both a getter and a setter). However, that property declaration can’t be implemented as a constant property or a read-only computed property. If a property declaration includes only the get keyword, it can be implemented as any kind of property.

Swift Protocols: Difference between { get } and { get set } with concrete examples?

protocol — is a requirement of some minimal interface of the type implementing it.

  • var name: Type { get } requires type to have property with at least a getter (accessible from outside of the type, not private), i.e. outside code should be able to read value of the property. In the implementing type it could be let name: Type, var name: Type, private(set) var name: Type, fileprivate(set) var name: Type, etc.

  • var name: Type { get set } requires type to have property with both accessible getter and setter, i.e. outside code should be able to read and write to the property. Here only var name: Type would be allowed.

If protocol requires for getter but you also provide a setter — it's not against protocol requirements.
But if protocol requires for both getter and setter — you must provide both, and not having any of them won't be valid implementation.


Your Person class defined both properties as var(with accessible getter and setter) therefore you can change them both. But PersonProtocol haven't required ability to set firstName.

And as @JoakimDanielson shows, if you will use just interface required by protocol you won't be to change the firstName value.

Swift protocol settable property through a read-only property

Change your protocol declaration to this:

protocol AProtocol:class {
var name: String { get set }
}

Otherwise, it is taken by default as a value type. Changing a value type's property replaces the value type instance (as shown by the setter observer). And you can't do that if the reference is a let reference.

Why am I allowed to set a read only property of a protocol using a struct that inherits said protocol?

What am I doing wrong to make it a true read only property to where I can't set it?

There is a difference between a protocol (a set of rules) and the type (i.e. your struct) that adopts the protocol.

  • Your protocol rule says that readOnlyProperty should be readable.

  • Your struct obeys by making it readable, and also makes it writable. That is not illegal, so all is well — and readOnlyProperty in your struct is read-write.

What would have been illegal would be the inverse, i.e. for the protocol to declare a property read-write but the adopter to declare it read-only. That situation didn't arise in your example, but if it had, the compiler would have stopped you.

Specify a settable property/variable in a protocol

The protocol might be implemented by either classes and structs - that prevents you from changing the internal status of an instance of a class or struct implementing that protocol using an immutable variable.

To fix the problem you have to either declare the food variable as mutable:

func eat() {
var food = nextItem
food.eaten = true // (!) ERROR: Cannot assign to result of this expression
}

or declare the EdibleThing protocol to be implementable by classes only:

protocol EdibleThing : class {
var eaten: Bool { get set }
}

Note that this happens because food is a variable of EdibleThing type - the compiler doesn't know if the actual instance is a value or reference type, so it raises an error. If you make it a variable of a class type, like this:

let food: Pickle = nextItem as! Pickle

the compiler knows without any ambiguity that it's a reference type, and in that case it allows the assignment. But I guess that breaks your app logic... so consider it just as an example

How to conform to a protocol's variables' set & get?

From the Swift Reference:

Property Requirements

...

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.

...

Property requirements are always declared as variable properties, prefixed with the var keyword. Gettable and settable properties are indicated by writing { get set } after their type declaration, and gettable properties are indicated by writing { get }.

In your case

var height: Int  {return 5} // error!

is a computed property which can only be get, it is a
shortcut for

var height: Int {
get {
return 5
}
}

But the Human protocol requires a property which is gettable and settable.
You can either conform with a stored variable property (as you noticed):

struct Boy: Human { 
var height = 5
}

or with a computed property which has both getter and setter:

struct Boy: Human { 
var height: Int {
get {
return 5
}
set(newValue) {
// ... do whatever is appropriate ...
}
}
}

Swift protocol property of type Set Self

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 protocols mutability

The protocol requirement is

a variable name which can be read

which doesn't mean that the variable in a struct adopting this protocol is necessarily read-only.

In the code you are changing the variable directly in the Driver type, the protocol is not involved.

On the other hand if you annotate the protocol type you get the expected error

var driver : Person = Driver(name: "Ryan")
driver.name = "Changed!" // Cannot assign to property: 'name' is a get-only property


Related Topics



Leave a reply



Submit