#swift
#swift
Вопрос:
Я хочу создать функцию для изменения исходного значения моей переменной. например
class Something {
var name:String = " John Diggle "
name.trim()
print(name)
// prints out " John Diggle "
// what I wanna do is to make it so that I don't do this
name = name.trim()
print(name)
// prints out "John Diggle"
}
extension String {
func trim() -> String{
return self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
}
есть ли способ изменить значение переменной внутри функции, не выполняя name = name.trim()
?
Ответ №1:
Может быть, что-то вроде этого?
extension String {
mutating func trim() {
self = self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
}
Затем вы можете использовать ее как name.trim()
Комментарии:
1. Предположение:
mutating
Атрибут сообщает компилятору, что функция не может быть вызвана для констант?2. Да, так и должно быть
var
, поскольку String — это структура, а не класс, она не может изменить значение, как только оно разрешено, то же самое с вопросом, хотя это должно бытьvar
уже,mutating
ключевое слово означает, что вы пытаетесь изменить значениеself
внутри функции3. о. не знал, что я могу использовать функцию изменения для расширений строк. Спасибо
Ответ №2:
Просто чтобы расширить ответ Tj3n (который вы должны принять), появляющееся соглашение в API заключается в использовании прошедшего времени глагола (например, trimmed
) для возврата новой строки, метод, который вы можете использовать как для констант, так и для переменных, и использовать настоящее время (например, trim
) для изменяющегося представления, которое может использоваться только для переменных:
extension String {
func trimmed() -> String {
return self.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet())
}
mutating func trim() {
self = self.trimmed()
}
}
Таким образом, либо:
var name = " John Diggle "
name.trim()
print("'(name)'")
Или:
let name = " John Diggle "
let trimmedName = name.trimmed()
print("'(trimmedName)'")
Комментарии:
1. спасибо, я буду иметь это в виду, учитывая мои соглашения об именовании до сих пор
Ответ №3:
Вы можете использовать didSet
для обрезки строки при каждом ее изменении:
class Something {
var name: String = "" {
didSet {
name = name.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
}
let s = Something()
s.name = " John Diggle "
// Note that we never call trim in the outside code
print("'(s.name)'")
Комментарии:
1. Я не знаю, почему это было отклонено. Это неплохое решение.
2. @NRitH возможно, потому, что это не расширение? (согласно запросу)
3. Это зависит от предположений, которые не были четко сформулированы в OP. Обрезка пробелов в начале и конце имени является разумным ожиданием. OP попросил мутировать
name
в одном вызове функции (вместо ее повторного назначения), но конечная цель, возможно, была идентичной4. @CodeDifferent заголовок довольно четко запрашивает расширение
5. @NRitH — Я не думаю, что это заслуживало отрицательного голосования, но это тоже не очень хороший шаблон. Когда вы устанавливаете свойство, вы ожидаете, что оно будет таким, каким вы его задали. Вероятно, в данном конкретном случае это не проблема, но, как правило, такого рода скрытое поведение становится помехой при обслуживании. Если бы я хотел такого поведения, я бы (а) использовал частное сохраненное свойство; (б) имел открытый метод для обновления значения; и (в) имел вычисляемое свойство для извлечения значения. Но этот общедоступный интерфейс должен использовать имена, которые дают понять, что, возможно, имело место какое-то преобразование.