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

I'm following a tutorial on the protocol oriented programming paradigm in which I'm confused by something I thought was rather simple which is read only properties of protocols or getters and setters. My understanding is that a read only property is signified by using the keyword 'get' when declaring a variable within a protocol. I was excited so I quickly coded created a playground to see if my thinking was accurate however it appears that I can still change the property which I thought was read only. What am I doing wrong to make it a true read only property to where I can't set it?
protocol FullName {
var firstName: String {get set}
var lastName: String {get set}
var readOnlyProperty: String {get}
}
struct OuttaBeerOuttaHere: FullName {
var firstName: String
var lastName: String
var readOnlyProperty: String = "Jack! Jack!...Line from Titanic"
}
var leonardoDicaprio = OuttaBeerOuttaHere.init(firstName: "Leonardo", lastName: "Dicaprio", readOnlyProperty: "WTF")
print(leonardoDicaprio.readOnlyProperty) //prints "WTF"
leonardoDicaprio.readOnlyProperty = "what now"
print(leonardoDicaprio.readOnlyProperty) //prints "what now"

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.

Your protocol doesn't declare readOnlyProperty as a read-only property. It only requires that implementations of that protocol have at least gettable readOnlyProperty property. To allow mutations of that property or not is up to implementation itself.

From Docs
Here’s an example of a protocol with a single instance property requirement:
protocol FullyNamed {
var fullName: String { get }
}
The FullyNamed protocol requires a conforming type to provide a
fully-qualified name. The protocol doesn’t specify anything else about
the nature of the conforming type—it only specifies that the type must
be able to provide a full name for itself. The protocol states that
any FullyNamed type must have a gettable instance property called
fullName, which is of type String
it's a requirement from the protocol not a define

Related

Invalid redeclaraciton of property for protocol when base class has optional property of same name

I have a protocol that has a property name: String. I have a base class that has a property of name: String?. When I try to adopt the protocol, I keep getting invalid redeclaration error. How do I redeclare a property of the same name but optional?
protocol Targetable {
var id: String { get }
var name: String { get }
}
You cannot have several properties with the same name, but different types, so you cannot achieve what you are trying to achieve. Even if you changed the type of name of a completely unrelated type (let's say Int), you'd get the same error, this has nothing to do with one of the two declarations being Optional.

In Swift do you not have to use a getter and setter when creating an object type, such as class, that conforms to a protocol requiring so?

protocol UserType {
var name: String { get }
var age: Int { get set }
struct Person: UserType {
var name: String //<- why is this okay?
var age: Int //<- why is this okay? dont we need a getter setter
}
let somePerson = Person(name: "Billy", age: 22)
Why in the above examples, we dont use get constructs or set constructs for age and a get construct for name? Is it because in the protocol when the property is said to "{ get set }" that essentially means it has to be able to be read and has to be able to be changed, which can be done through a declaration in the syntax of a stored property?
Thanks!
protocol UserType {
var name: String { get }
var age: Int { get set }
}
The important thing to understand is that { get } and { get set } are merely notations. They have nothing to do with "getter and setter". They are merely ways of describing to the compiler what the protocol's requirements are. (You could argue that the notation is confusing or misleading, but it's what we've got, so we have to live with it.)
So, basically, all this says is:
An adopter must declare a name String instance property.
An adopter must also declare an age Int instance property and that property must be writable.
That's all it means. Well, you have satisfied those requirements in your adopter (Person). Your code is legal. The end.
One thing to note first: Every property has an implicit getter and setter unless otherwise stated. e.g. a simple var age: Int implicitly has a get and set, and let age: Int implicitly has a get. When you declare a manual getter and setter, you're overriding something, not creating something that didn't otherwise exist.
As for protocols, in explicit terms:
var name: String { get } means the adhering Type must have a property with a signature of name:String that can be read, AKA. get
var age: Int { get set } means the adhering Type must have a property with a signature of age:String that can be read or assigned, AKA get and set
Note that these rules are inclusive not exclusive. The requirements don't care how they are satisfied, and don't disallow anything else.
This means with your given example, a property of let name: String would work because it only requires access, but let age: Int wouldn't work, because it cannot be changed. It also doesn't care about internal details, so using computed properties, private setters, etc. is fine as long as they have the necessary access.

Is there a CustomStringConvertible equivalent for type in Swift?

I want to implement a protocol similar to CustomStringConvertible for a given type but for instance.
My need is to display type properties values without creating an instance valuer for this purpose. Of course I can add CustomStringConvertible protocol to this type then create an instance value only to invoke description. But I wonder if there is such feature in Swift?
Overview:
type(of:) is a function that returns the type of an instance in a String
self can be used on the Type
Code:
struct Something {
}
print(type(of: Something.self))
Create your own protocol that will include a static var.
static var desc: String { get set }
on classes that conform to your protocol use it like this:
MyClass.desc

Can I have a Swift protocol without functions

Consider this typical example, sometimes seen in tutorials, etc (even in Apple's code):
protocol Nameable {
var name: String {get}
}
struct Person : Nameable {
var name: String
}
My question is, what would be the benefit of this pattern? I can understand it once a function is added to a protocol, but what could be a good application for a protocol with just one or more variables? Why not just add name to each struct and class ?
Persons are not the only not the only things that you may want to name. Pets have names, roads have names, heck, some people name their cars.
What if we want to name each object in a collection of different objects? If we store those objects in a collection of Any, we don't have any way to guarentee that all objects have names.
This is where protocols come in. By creating a Nameable protocol, we can create a collection of Nameable objects, and be certain that all the objects within are guaranteed to have a name.
Here's an example:
protocol Nameable {
var name: String {get}
}
struct Person : Nameable {
let name: String
let age: Int
// other properties of a Person
}
struct Pet : Nameable {
let name: String
let species: String
// other properties of a Pet
}
struct Car : Nameable {
let name: String
let horsepower: Double
// other properties of a Car
}
let namableItems: [Nameable] = [
Person(name: "Steve", age: 21),
Pet(name: "Mittens", species: "Cat"),
Car(name: "My Pride and Joy", horsepower: 9000)
]
for nameableItem in namableItems {
print("\(nameableItem.name) is a \(nameableItem.dynamicType).")
}
Which prints:
Steve is a Person.
Mittens is a Pet.
My Pride and Joy is a Car.
You can try it here.
Basically you make a promise that your class / struct will contain defined properties.
For structures this is very important because they can't be subclassed.
Also, subclass can only have 1 superclass so you can't create Person who has more than one parent.
I would recommend you to read this article about why use protocols over subclassing and the main purpose of using them:
http://alisoftware.github.io/swift/protocol/2015/11/08/mixins-over-inheritance/
The key to the answer lies in the word protocol.
Protocol is a system of rules that explain the correct conduct and
procedures to be followed in formal situations.
That said, when you state that an object (struct, enum, class, ..) must conform to a protocol, you are obliged to respect it. If you do not, Xcode throws an error.
So one of the main, (absolutely not the only utility) is that you can not forget to include the attributes and / or functions in the various objects.
This could be very useful if multiple developers are working on the same code, or simply to avoid potential human error of distraction :) .
Another great advantage of the protocols is that they can be used as types.
Therefore a struct, enum, or different classes, which inherit the same protocol, they can all be traced to the same type.

Read-only properties of protocols in Swift

From the "Learn the Essentials of Swift" playground, there's an example protocol:
protocol ExampleProtocol {
var simpleDescription: String { get }
func adjust()
}
There's a short passage after this example that reads:
Note: The { get } following the simpleDescription property indicates that it is read-only, meaning that the value of the property can be viewed, but never changed.
Additionally an example is given of a class conforming to this protocol:
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
However how does this class conform to the protocol? What's stopping me from mutating simpleDescription? What don't I understand?
There's no way to specify in a protocol that you must have a read-only property. Your protocol asks for a simpleDescription property, and allows but does not require a setter.
Note also that the only reason you may mutate simpleDescription is because you know your a is of type SimpleClass. If we have a variable of type ExampleProtocol instead...
var a: ExampleProtocol = SimpleClass()
a.simpleDescription = "newValue" //Not allowed!
Protocols place requirements on object's interface, but do not restrict implementation from providing more operations than that.
In this example, the protocol requires a readable simpleDescription property and adjust() method. The class provides that, so it conforms to the protocol. In other words, this protocol says implementation must have get operation, but it does not prohibit them from also having set.
You will not be able to mutate simpleDescription via that protocol interface, because it does not provide such operation, but nothing prevents you from mutating it through different interface — in this example, the interface of the implementing class.
Found this and thought it may be of interest in addition to the excellent answer already provided:
If a protocol requires a property to be gettable and settable, that property requirement cannot be fulfilled by a constant stored property or a read-only computed property. If the protocol only requires a property to be gettable, the requirement can be satisfied by any kind of property, and it is valid for the property to be also settable if this is useful for your own code.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2.2).” iBooks. https://itun.es/us/jEUH0.l