What is the difference between a property and a variable in Swift?
Asked Answered
K

3

7

From a few initial tutorials, I see that properties belong to a Class and are essentially 'global variables' as used in the C++ world (coded in this years ago). I also see variables as more of a 'local' entities only used / storing information within a method.

Then I came across this Quora thread: https://www.quora.com/Apple-Swift-programming-language/What-is-the-difference-between-a-property-and-a-variable Now I see properties being able to execute code associated with their invocation. This is very cool, but also opened up a whole bunch of other questions for me.

Are there other simple and clear ways to remember the distinction between a property and a variable?

Kalliekallista answered 20/11, 2015 at 22:39 Comment(0)
P
6

Local variables are just things that you work with. You have full control over these, and if you change a variable in a function, nothing outside of your function is ever gonna know. If I write a framework and you use it, and I decide to change something about a function's local variables, your app that uses my framework will keep working just as if nothing changed.

Classes, on the other hand, describe a contract. When you use a class, you have access to everything they publicly advertise. This means that if I write a framework and you use it, if I ever change or remove a public member on a class, your code will break if you were previously using that member.

For this reason, in many languages, it's bad practice to mark instance variables as public. Instance variables having no logic attached, if I want at some point to trigger something when a field is changed or if I want to remove the field entirely (and instead report a value in a sub-object or something), then I'm stuck with changing the public contract (turning the field in a pair of get/set methods, for instance), and possibly breaking your code.

Swift makes properties an indirection for this reason. Swift properties can be treated as dumb values for the most part, but if you ever need to change from a stored value to a computed value or something, you can do it without changing your class's interface. That way, you don't break existing code that relies on the property.

Pauly answered 20/11, 2015 at 22:51 Comment(5)
Thanks! This makes a lot of sense - the new concept I picked up from your response is the get/set methods and really the computed value vs. stored value states for a property. The tutorial I'm studying did not yet get into that depth about properties. Takeaway: properties can be tricky as they are 'global' and variables are simpler to control.Kalliekallista
A small thought about your Takeaway point, properties are always global. Its not the case always because if I declare a property with access specifier "private", its scope limits to that of the class and is no more 'global'.Or doing so turn it into variable. No right. What do u say?Rotarian
@G.Abhisek, I don't understand your question. I'm not sure where it says that properties are always global. Also, at the class level, there is no distinction between a variable and a property, so you can't "turn" a property into a variable.Pauly
@Pauly Sorry I was replying to the comment of Madhu Chamarty's take away point on your answer.Rotarian
Well, he probably just hadn't got to the point of access control yet.Pauly
O
12

Properties belong to an object, whereas variables do not. A variable can be declared without having to be associated with a particular class, or other object. A property must be associated with a particular object (i.e.: a class, enum, or struct)

Oversubtle answered 20/11, 2015 at 22:48 Comment(2)
Thanks! That is how I understood them. Still trying to understand exact implications of a parent class's variables inside a subclass's object's methods. When an object from a subclass overrides a parent class's method, it can change the corresponding local variable's value, but still not affect that variable's value in the parent class. Did I understand this right?Kalliekallista
Yup, overriding a method's variable in the subclass does not effect the variable in the parent class.Oversubtle
P
6

Local variables are just things that you work with. You have full control over these, and if you change a variable in a function, nothing outside of your function is ever gonna know. If I write a framework and you use it, and I decide to change something about a function's local variables, your app that uses my framework will keep working just as if nothing changed.

Classes, on the other hand, describe a contract. When you use a class, you have access to everything they publicly advertise. This means that if I write a framework and you use it, if I ever change or remove a public member on a class, your code will break if you were previously using that member.

For this reason, in many languages, it's bad practice to mark instance variables as public. Instance variables having no logic attached, if I want at some point to trigger something when a field is changed or if I want to remove the field entirely (and instead report a value in a sub-object or something), then I'm stuck with changing the public contract (turning the field in a pair of get/set methods, for instance), and possibly breaking your code.

Swift makes properties an indirection for this reason. Swift properties can be treated as dumb values for the most part, but if you ever need to change from a stored value to a computed value or something, you can do it without changing your class's interface. That way, you don't break existing code that relies on the property.

Pauly answered 20/11, 2015 at 22:51 Comment(5)
Thanks! This makes a lot of sense - the new concept I picked up from your response is the get/set methods and really the computed value vs. stored value states for a property. The tutorial I'm studying did not yet get into that depth about properties. Takeaway: properties can be tricky as they are 'global' and variables are simpler to control.Kalliekallista
A small thought about your Takeaway point, properties are always global. Its not the case always because if I declare a property with access specifier "private", its scope limits to that of the class and is no more 'global'.Or doing so turn it into variable. No right. What do u say?Rotarian
@G.Abhisek, I don't understand your question. I'm not sure where it says that properties are always global. Also, at the class level, there is no distinction between a variable and a property, so you can't "turn" a property into a variable.Pauly
@Pauly Sorry I was replying to the comment of Madhu Chamarty's take away point on your answer.Rotarian
Well, he probably just hadn't got to the point of access control yet.Pauly
B
5

Swift variable, constant, Property

[Swift types]

variable - named storage of address. Every variable has a type which defines a memory size, attributes and behaviours

Swift variable and constants

constant is a variable but can not be modified after definition.

//definition
var <name> = <initial_value>
//type annotation
var <name>: <Swift_type> [= <initial_value>] // [] is optional

//var - variable
var myVariable1 = 11 
var myVariable2: Int 
myVariable2 = 12

//let - constant
let myConstant1 = 21 
let myConstant2: Int 
myConstant2 = 22

Global and local variable

Global variable is a variable which is defined out of function, class. Local variable is: variable inside a type context(class, struct, enum)[About], inside a function, function parameter

Property

property - associate value with a type context. It is a variable + bounded getter/setter. It has field syntax but uses methods(getter/setter) under the hood.

Stored properties and computed properties

They can belong to instance(instance property) or type(type property):
Stored property (class, structure)
Computed property (class, structure, enum)

Stored property - is a local variable -> variable inside a type context. Swift stored property does not support instance variable like Objective-C.

  • variable stored properties - var
  • constant stored properties - let

It supports property observers (willSet, didSet)

Computed property - provide getter and optional setter to calculate a value every time

public class Person {
    var firstName = "John"
    var lastName = "Wick"
    
    var fullNameComputedProperty: String {
        get {
            return "\(firstName) \(lastName)"
        }
        
        //optional
        set {
            let arr = newValue.split(separator: " ")
            firstName = String(arr[0])
            lastName = String(arr[1])
        }
    }
    
    var addressStoredProperty: String {
        //Property Observers
        willSet {
            print("old address:\(addressStoredProperty)")
            print("new address:\(newValue)")
            //addressStoredProperty is not updated yet
        }
        didSet {
            print("old address:\(oldValue)")
            print("new address:\(addressStoredProperty)")
        }
    }
}

Lazy Stored property

Property is calculate during first access to it(on demand)

  • only var lazy because let must have a value during initialization

Init/customize stored property by closure

Official doc

You are able to init/setup/customise a stored property with a help of closure

  • () at the end executes the closure immediately and assign a value to stored property(calculate and return a value).
  • in initializing case it is not possible to access to any instance variable or function because it has not initialized yet
  • in initializing case it will be executed only once for every object or if you use static - once for the class[Example]

Examples

func testStoredPropertyWithClosure() {
    class ClassA { }
    
    class ClassB {
        static let staticStoredProperty: ClassA = {
            //is called only when you access to it like ClassB.staticStoredProperty
            print("init staticStoredProperty")
            return ClassA()
        }()
        
        var storedProperty: ClassA = {
            print("init storedProperty")
            //self.foo() //Error: Class declaration cannot close over value 'self' defined in outer scope
            return ClassA()
        }()
        
        func foo () {
            storedProperty = {
                print("customize storedProperty")
                return ClassA()
            }()
        }
    }
    
    let b = ClassB()
    b.foo()
    
    ClassB.staticStoredProperty
}

closure stored property vs Computed property

  • closure stored property is called once and can be changed after initialization(if it is var)
  • Computed property is calculated every time when it is called

[Java variable, property...]

Bib answered 29/3, 2020 at 11:9 Comment(1)
Coming from a C# background, the main difference between fields and properties is that you can get the address of a field and pass it around by-referenc (such that other code can directly write to it) which you can't do with a property - but in Swift (to me, at least) it's unclear when a variable stored property represents a directly addressable field or not: in your first example, I assume the syntax var firstName = "John" represents a field that can be passed by reference, but what if you want a simple mutable property without consumers being able to directly reference it like a field?Salted

© 2022 - 2024 — McMap. All rights reserved.