Вычислимое свойство только для чтения vs функция в Swift
В сеансе Введение в Swift WWDC показано свойство description
только для чтения:
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description)
Есть ли какие-либо последствия для выбора вышеупомянутого подхода с использованием метода:
class Vehicle {
var numberOfWheels = 0
func description() -> String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description())
Мне кажется, что наиболее очевидными причинами, по которым вы выбрали вычисляемое свойство только для чтения, являются:
- Семантика - в этом примере для
description
имеет смысл свойство класса, а не действие, которое оно выполняет.
- Краткость/Ясность - предотвращает необходимость использования пустых круглых скобок при получении значения.
Очевидно, что приведенный выше пример слишком прост, но есть ли другие веские причины выбирать один за другим? Например, существуют ли какие-то функции функций или свойств, которые могли бы определять ваше решение?
N.B. На первый взгляд это кажется довольно распространенным вопросом ООП, но я заинтересован в том, чтобы узнать какие-либо особенности, зависящие от Swift, которые наилучшим образом помогут при использовании этого языка.
Ответы
Ответ 1
Мне кажется, что это в основном вопрос стиля: я предпочитаю использовать свойства только для: свойств; что означает простые значения, которые вы можете получить и/или установить. Я использую функции (или методы), когда выполняется фактическая работа. Возможно, что-то нужно вычислять или читать с диска или из базы данных: в этом случае я использую функцию, даже когда возвращается только простое значение. Таким образом, я могу легко увидеть, дешев (свойства) или, возможно, дорогой (функции).
Мы, вероятно, получим больше ясности, когда Apple опубликует некоторые соглашения о кодировании Swift.
Ответ 2
В то время как вопрос о вычисленных свойствах против методов в целом является жестким и субъективным, в настоящее время в случае Swift существует один важный аргумент для предпочтения методов над свойствами. Вы можете использовать методы в Swift как чистые функции, которые не соответствуют свойствам (как и для Swift 2.0 beta). Это делает методы намного более мощными и полезными, поскольку они могут участвовать в функциональной композиции.
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)))
Ответ 3
Есть разница:
Если вы используете свойство, вы можете в конечном итоге переопределить его и сделать его чтение/запись в подклассе.
Ответ 4
Поскольку время выполнения одинаково, этот вопрос относится и к Objective-C. Я бы сказал, со свойствами вы получите
- возможность добавления сеттера в подкласс, создавая свойство
readwrite
- возможность использования KVO/
didSet
для уведомлений об изменениях
- В более общем плане вы можете передать свойство методам, которые ожидают ключевые пути, например. сортировка запроса выборки
Что касается чего-то определенного для Swift, единственный пример, который у меня есть, это то, что вы можете использовать @lazy
для свойства.
Ответ 5
Хорошо, вы можете использовать советы Kotlin https://kotlinlang.org/docs/reference/coding-conventions.html#functions-vs-properties.
В некоторых случаях функции без аргументов могут быть взаимозаменяемыми с свойствами только для чтения. Хотя семантика подобна, являются некоторыми стилистическими соглашениями о том, когда следует отдать предпочтение друг другу.
Предпочитает свойство над функцией, когда базовый алгоритм:
- не бросает
- имеет O (1)
- сложность дешево вычислять (или закрывать при первом запуске)
- возвращает тот же результат по вызовам
Ответ 6
Бывают ситуации, когда вы предпочли бы вычисленное свойство над нормальными функциями. Например: возвращение полного имени человека. Вы уже знаете имя и фамилию. Таким образом, свойство fullName
является не функцией. В этом случае это вычисленное свойство (поскольку вы не можете установить полное имя, вы можете просто извлечь его с использованием имени и последнего имени)
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
Ответ 7
Исторически описание является свойством в NSObject, и многие ожидали бы, что он продолжит то же самое в Swift. Добавление parens после этого только добавит путаницу.
EDIT:
После яростного downvoting я должен что-то прояснить - если к нему обращаются через точечный синтаксис, его можно считать свойством. Неважно, что под капотом. Вы не можете получить доступ к обычным методам с точечным синтаксисом.
Кроме того, вызов этого свойства не требовал дополнительных парнеров, например, в случае Swift, что может привести к путанице.