Computed read-only property vs function in Swift

In the Introduction to Swift WWDC session, a read-only property description is demonstrated:

class Vehicle {
    var numberOfWheels = 0
    var description: String {
        return "\(numberOfWheels) wheels"
    }
}

let vehicle = Vehicle()
println(vehicle.description)

Are there any implications to choosing the above approach over using a method instead:

  • What is the correct way to create a custom setter for a weak property in Objective C?
  • Objective C calling method dynamically with a string
  • Adding a getter makes using an underscore incorrect syntax
  • How to pass dictionary as a parameter in the method in Swift?
  • Conversion to Automatic Reference Counting (ARC): 'Use of undeclared identifier' errors
  • Command failed due to signal: Segmentation fault: 11 while emitting IR SIL function
  • class Vehicle {
        var numberOfWheels = 0
        func description() -> String {
            return "\(numberOfWheels) wheels"
        }
    }
    
    let vehicle = Vehicle()
    println(vehicle.description())
    

    It seems to me that the most obvious reasons you would choose a read-only computed property are:

    • Semantics – in this example it makes sense for description to be a property of the class, rather than an action it performs.
    • Brevity/Clarity – prevents the need to use empty parentheses when getting the value.

    Clearly the above example is overly simple, but are there other good reasons to choose one over the other? For example, are there some features of functions or properties that would guide your decision of which to use?


    N.B. At first glance this seems like quite a common OOP question, but I’m keen to know of any Swift-specific features that would guide best practice when using this language.

    8 Solutions Collect From Internet About “Computed read-only property vs function in Swift”

    It seems to me that it’s mostly a matter of style: I strongly prefer using properties for just that: properties; meaning simple values that you can get and/or set. I use functions (or methods) when actual work is being done. Maybe something has to be computed or read from disk or from a database: In this case I use a function, even when only a simple value is returned. That way I can easily see whether a call is cheap (properties) or possibly expensive (functions).

    We will probably get more clarity when Apple publishes some Swift coding conventions.

    While a question of computed properties vs methods in general is hard and subjective, currently there is one important argument in the Swift’s case for preferring methods over properties. You can use methods in Swift as pure functions which is not true for properties (as of Swift 2.0 beta). This makes methods much more powerful and useful since they can participate in functional composition.

    func fflat<A, R>(f: (A) -> () -> (R)) -> (A) -> (R) {
        return { f($0)() }
    }
    
    func fnot<A>(f: (A) -> Bool) -> (A) -> (Bool) {
        return { !f($0) }
    }
    
    extension String {
        func isEmptyAsFunc() -> Bool {
            return isEmpty
        }
    }
    
    let strings = ["Hello", "", "world"]
    
    strings.filter(fnot(fflat(String.isEmptyAsFunc)))
    

    There is a difference:
    If you use a property you can then eventually override it and make it read/write in a subclass.

    Since the runtime is the same, this question applies to Objective-C as well. I’d say, with properties you get

    • a possibility of adding a setter in a subclass, making the property readwrite
    • an ability to use KVO/didSet for change notifications
    • more generally, you can pass property to methods that expect key paths, e.g. fetch request sorting

    As for something specific to Swift, the only example I have is that you can use @lazy for a property.

    Well, you can apply Kotlin ‘s advices https://kotlinlang.org/docs/reference/coding-conventions.html#functions-vs-properties.

    In some cases functions with no arguments might be interchangeable
    with read-only properties. Although the semantics are similar, there
    are some stylistic conventions on when to prefer one to another.

    Prefer a property over a function when the underlying algorithm:

    • does not throw
    • has a O(1)
    • complexity is cheap to calculate (or caсhed
      on the first run)
    • returns the same result over invocations

    There are situations where you would prefer computed property over normal functions. Such as: returning the full name of an person. You already know the first name and the last name. So really the fullName property is a property not a function. In this case, it is computed property (because you can’t set the full name, you can just extract it using the firstname and the lastname)

    class Person{
        let firstName: String
        let lastName: String
        init(firstName: String, lastName: String){
            self.firstName = firstName
            self.lastName = lastName
        }
        var fullName :String{
            return firstName+" "+lastName
        }
    }
    let william = Person(firstName: "William", lastName: "Kinaan")
    william.fullName //William Kinaan
    

    Historically description is a property on NSObject and many would expect that it continues the same in Swift. Adding parens after it will only add confusion.

    EDIT:
    After furious downvoting I have to clarify something – if it is accessed via dot syntax, it can be considered a property. It doesn’t matter what’s under the hood. You can’t access usual methods with dot syntax.

    Besides, calling this property did not require extra parens, like in the case of Swift, which may lead to confusion.

    In the read-only case, a computed property should not be considered semantically equivalent to a method, even when they behave identically, because dropping the func declaration blurs the distinction between quantities that comprise the state of an instance and quantities that are merely functions of the state. You save typing () at the call site, but risk losing clarity in your code.

    As a trivial example, consider the following vector type:

    struct Vector {
        var x, y: Double
        func length() -> Double {
            return sqrt(x*x + y*y)
        }
    }
    

    By declaring the length as a method, it’s clear that it’s a function of the state, which depends only on x and y.

    On the other hand, if you were to express length as a computed property

    struct VectorWithLengthAsProperty {
        var x, y: Double
        var length: Double {
            return sqrt(x*x + y*y)
        }
    }
    

    then when you dot-tab-complete in your IDE on an instance of VectorWithLengthAsProperty, it would look as if x, y, length were properties on an equal footing, which is conceptually incorrect.