Using Swift Computed Properties Vs. Accessor and Mutator Functions - swift

Coming from a Java background where getters and setters are commonly used to provide a public interface for private fields, I see computed properties in swift as an integrated modification of such accessor and mutator methods. I understand that computed properties are designed to modify or retrieve the value of any other field, while providing functionality for additional code.
Given that Swift computed properties appear to have the same purpose and usage of Java getters and setters, would there be any significant performance difference in the following swift declarations? Is there any performance advantage using computed properties over accessors and mutators?
Computed property
private var privateField: Int = 0
var field: Int { get { return privateField } set { privateField = newValue } }
Getter / Setter
private var privateField: Int = 0
func getField() -> Int {
return privateField
}
func setField(newValue: Int) {
privateField = newValue
}
In terms of readability, I personally think the separate methods approach looks neater and more organized, and if there were no performance issues I would use it over get {} set {}

The key here is to write idiomatic Swift code; a property in Swift is expected to be:
var field: Int = 0 {
didSet {
//Any consequences of setting here
}
}
Your getField()/setField() solution is unusual and not an expected use of the language. Readability is the most important aspect here, but this aligns with performance: I'm sure as the language is further developed and optimized, it will definitely ensure that its own idiomatic code continues to run quickly, but it may not care about the performance of your getField()/setField().

Related

Naming Convention for Methods and Properties in Swift. Can I use "get", "set" and "is" Keywords?

When I create a function in Swift, can I use "get" and "set" words? For instance can I declare a function as func getAuthorizedUsers() instead of func authorizedUsers()? In ObjectiveC get and set keywords are not suggested to use when declaring functions. How about in Swift?
Also, when declaring properties can I use "is" keyword? For instance:
public var isAuthorized: Bool {
get {
return true
}
}
I have read Swift naming convention documents but I couldn't find the answer of my question. Thank you.
The rules are all outlined here.
For get, that clearly violates the "Omit needless words" rule. If a method returns something, the call site will know that it is used to get some value. You don't need to repeat that idea. You can consider turning this into a computed property if no parameters are required.
For set, it might be appropriate sometimes. If your method only need one parameter and there is a corresponding getter,
func getFoo() -> Int {
...
}
func setFoo(_ foo: Int) {
...
}
That's a pretty good sign that this can be turned into a computed property:
var foo: Int {
get { ... }
set { ... }
}
A good example where it is appropriate to have set is the UIButton.setTitle method. It takes in two parameters, so a computed property wouldn't work.
For is, that clearly conforms to the rule "Uses of Boolean methods and properties should read as assertions about the receiver". So yes, you should use it for boolean members.

what is the difference between these two in swift 3 [duplicate]

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:
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 for choosing 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.
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.
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
complexity is cheap to calculate (or caсhed
on the first run)
returns the same result over invocations
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.
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 {
let 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 {
let 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.
From the performance perspective, there seems no difference. As you can see in the benchmark result.
gist
main.swift code snippet:
import Foundation
class MyClass {
var prop: Int {
return 88
}
func foo() -> Int {
return 88
}
}
func test(times: u_long) {
func testProp(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = Date()
for _ in 0...times {
_ = myClass.prop
}
let ending = Date()
return ending.timeIntervalSince(starting)
}
func testFunc(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = Date()
for _ in 0...times {
_ = myClass.prop
}
let ending = Date()
return ending.timeIntervalSince(starting)
}
print("prop: \(testProp(times: times))")
print("func: \(testFunc(times: times))")
}
test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)
Output:
prop: 0.0380070209503174
func: 0.0350250005722046
prop: 0.371925950050354
func: 0.363085985183716
prop: 3.4023300409317
func: 3.38373708724976
prop: 33.5842199325562
func: 34.8433820009232
Program ended with exit code: 0
In Chart:
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
Semantically speaking, computed properties should be tightly coupled with the intrinsic state of the object - if other properties don't change, then querying the computed property at different times should give the same output (comparable via == or ===) - similar to calling a pure function on that object.
Methods on the other hand come out of the box with the assumption that we might not always get the same results, because Swift doesn't have a way to mark functions as pure. Also, methods in OOP are considered actions, which means that executing them might result in side effects. If the method has no side effects, then it can safely be converted to a computed property.
Note that both of the above statements are purely from a semantic perspective, as it might well happen for computed properties to have side effects that we don't expect, and methods to be pure.
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.
An updated/fixed version of Benjamin Wen's answer incorporating Cristik's suggestion.
class MyClass {
var prop: Int {
return 88
}
func foo() -> Int {
return 88
}
}
func test(times: u_long) {
func testProp(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = CACurrentMediaTime()
for _ in 0...times {
_ = myClass.prop
}
let ending = CACurrentMediaTime()
return ending - starting
}
func testFunc(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = CACurrentMediaTime()
for _ in 0...times {
_ = myClass.foo()
}
let ending = CACurrentMediaTime()
return ending - starting
}
print("prop: \(testProp(times: times))")
print("func: \(testFunc(times: times))")
}
test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)

With Swift's didSet accessor do I still need to hide access to a property

I know that with typical Object Oriented programming you should not give access to your properties directly, rather have a function that interacts with that private property. With the fact that Swift has a didSet accessor for properties is it necessary to privatize that property or can I leave it not privatized and access it from it's parent
private var coins: Int = 0 {
didSet {
coinsLabel.text = "\(coins)"
}
}
func setCoins(amount: Int) {
coins = amount
}
func getCoinsAmount() {
return coins
}
//Setting the value from the parent
gameHUD.setCoins(amount: 50)
//retrieving the value from the parent
let coins = gameHUD.getCoinsAmount()
Or is it bad practice to just leave coins not privatized and set/get it directly from the parent
gameHUD.coins = 50
let coins = gameHUD.coins
No, you don't. Properties in Swift are a flexible, mature abstraction mechanism. As such, please go ahead and use it to define you public API. No need to export setters and getters.
For instance, tons of public properties are exported by almost any Apple/iOS native framework. Keep in mind that besides the property observers you mentioned (i.e., willSet and didSet) you can also define computed properties. As I said before, this is a full-blown abstraction mechanism.

Getter computed property vs. variable that returns a value

Is there a difference between a getter computed property and variable that returns a value? E.g. is there a difference between the following two variables?
var NUMBER_OF_ELEMENTS1: Int {
return sampleArray.count
}
var NUMBER_OF_ELEMENTS2: Int {
get {
return sampleArray.count
}
}
A computer property with getter and setter has this form:
var computedProperty: Int {
get {
return something // Implementation can be something more complicated than this
}
set {
something = newValue // Implementation can be something more complicated than this
}
}
In some cases a setter is not needed, so the computed property is declared as:
var computedProperty: Int {
get {
return something // Implementation can be something more complicated than this
}
}
Note that a computed property must always have a getter - so it's not possible to declare one with a setter only.
Since it frequently happens that computed properties have a getter only, Swift let us simplify their implementation by omitting the get block, making the code simpler to write and easier to read:
var computedProperty: Int {
return something // Implementation can be something more complicated than this
}
Semantically there's no difference between the 2 versions, so whichever you use, the result is the same.
They are identical since both define a read-only computed property. But the former is preferable because it is shorter and more readable than the latter.

Idiomatic Swift: Getter & Setter boiler plate coding

While migrating some projects from Objective-C to Swift, I find myself replacing the #property/#synthesize syntax with a lot more boiler-plate code.
For example, for every #property I am implementing, I currently use this pattern:
var foo: Foo? {
get {
return _foo
}
set {
_foo = newValue
}
}
var _foo: Foo?
It ends up adding quickly. Compare this with the 2 lines in Objective-C. That doesn't feel right.
Should I just replace the code using _foo in my ported classes with foo and skip the abstraction of each public var behind an interface entirely?
As #Amit89 pointed out, you can simply use _foo.
In your example, adding foo does exactly nothing, as you simply recreated the get and set functionality already supplied with _foo.
If you want to control how _foo is set you can use property observers:
var _foo: Foo? {
didSet { }
willSet { }
}
If you want to control how _foo is retrieved, then it would indeed make sense to create a private version of _foo, and then accessing it via a computed property:
private var _foo: Foo?
var foo: Foo? {
get {
// return `_foo` in some special way
}
// add a setter if you want to set `_foo` in some special way
}