Swift. Замена значения переменной с помощью функции расширения

#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 — Я не думаю, что это заслуживало отрицательного голосования, но это тоже не очень хороший шаблон. Когда вы устанавливаете свойство, вы ожидаете, что оно будет таким, каким вы его задали. Вероятно, в данном конкретном случае это не проблема, но, как правило, такого рода скрытое поведение становится помехой при обслуживании. Если бы я хотел такого поведения, я бы (а) использовал частное сохраненное свойство; (б) имел открытый метод для обновления значения; и (в) имел вычисляемое свойство для извлечения значения. Но этот общедоступный интерфейс должен использовать имена, которые дают понять, что, возможно, имело место какое-то преобразование.