Использование Getters и Setters для изменения значений без подкласса в Swift

Скажем, у меня есть класс, и когда я устанавливаю его свойство, я хочу, чтобы он добавил это свойство с типом файла, например .fileType:

class File {
    var fileName: String {
    get {
        return self.fileName
    }
    set {
        self.fileName = fileName + ".fileType"
    }
    }
}

Что я пытаюсь использовать следующим образом:

let newFile = File()
newFile.fileName = "My File"

К сожалению, переменная никогда не устанавливает:

Checkpoints

У меня есть два возможных способа обхода.

Вариант 1: соблюдать значение после установки

class File {
    var fileName: String = "" {
    didSet {
        self.fileName += ".fileType"
    }
    }
}

let file = File()
file.fileName = "SomeName" // SomeName.fileType

Но с этим я должен подождать, пока значение уже будет установлено, прежде чем я смогу его изменить. Для этого конкретного примера это не имеет особого значения; однако, я бы хотел, чтобы избежать этого.

Вариант 2: Подкласс

Это решение основано на примере здесь. Поиск 'speedLimitedCar'

class File {
    var fileName = ""
}

class SubFile: File {

    override var fileName: String {
    get {
        return super.fileName
    }
    set {
        super.fileName = newValue + ".fileType"
    }
    }
}

let subfile = SubFile()
subfile.fileName = "Hello" // Hello.fileType

Вопрос

Я мог бы просто создать вторичное свойство для хранения значения и доступа к нему в getNot/setter файла, но есть ли способ избежать этого и изменить свойство непосредственно в его getter/setter?

Ответ 1

Если вы используете set и get, тогда свойство должно быть вычислено. Для этого нет реального хранилища.

Этот код определяет var для хранения данных и вычисленного var для обработки доступа. Это похоже на то, что у вас было в Objective-C (за исключением того, что в Objective-C вы могли "скрыть" фактическую переменную, сделав ее частной или, совсем недавно, синтезировав ее никогда не упоминаемую в заголовке).

class File {
    // this stores the actual data, do not access it directly, consider it private
    var theFileName: String = ""

    // this is the real interface
    var fileName: String {
        get {
            return self.theFileName
        }
        set(name) {
            self.theFileName = name + ".fileType"
        }
    }
}

Вы также можете написать set следующим образом:

set {
    self.theFileName = newValue + ".fileType"
}

где newValue - это имя по умолчанию, если вы опускаете объявление аргумента для set.

Но то, что вы, вероятно, хотите сделать, это то, что вы уже сделали (и отклонено по неизвестным причинам):

var fileName: String = "" {
    didSet {
        self.fileName += ".fileType"
    }
}

Это правильный путь.

Обратите внимание: "Я должен подождать, пока значение уже будет установлено, прежде чем я смогу его изменить". неправда. Это похоже на то, но компилятор может очень хорошо оптимизировать код (и, вероятно, будет).