Свойство как тип функции в классе - PullRequest
2 голосов
/ 21 января 2020

Учитывая следующее:

enum Output {
    case typeA, typeB
}    

class SomeClass {
    var outputFunc: (Int) -> () = methodA // error here

    var output: Output = .typeA {
        didSet {
            if output == .typeA {
                outputFunc = methodA
            }
            else {
                outputFunc = methodB
            }
        }
    }

    func methodA(val: Int) {/* do something */} 
    func methodB(val: Int) {/* do something */} 
}

Все в didSet компилируется просто отлично, но когда я объявляю outputFunc Я получаю ошибку:

Невозможно преобразовать значение типа '(SomeClass) -> (Int) -> ()' для указанного типа '(Int) -> ()'

Я не уверен, как инициировать это свойство. Я попытался изменить его на self.methodA, но, очевидно, self еще не существует. Если я изменю тип outputFunc на (SomeClass) -> (Int) -> (), свойство компилируется, но didSet дает мне противоположную ошибку.

Ответы [ 2 ]

2 голосов
/ 21 января 2020

Это сообщение об ошибке может быть более информативным, поскольку настоящая ошибка действительно заключается в том, что вы пытаетесь получить доступ к self до его готовности, поскольку outputFunc - это свойство экземпляра, а methodA - метод экземпляра.

Чтобы решить эту проблему, вы можете просто сделать outputFunc lazy.

lazy var outputFunc: (Int) -> () = methodA
0 голосов
/ 21 января 2020

Поскольку вы сказали

, но очевидно, что self еще не существует

Похоже, вы понимаете, что не можете получить доступ к self до тех пор, пока все свойства были инициализированы в инициализаторе. Ну, methodA и self.methodA на самом деле одно и то же. Первое просто коротко для последнего, потому что self обычно не требуется, когда нет двусмысленности.

Одним из решений является инициализация его в инициализаторе, после инициализации outputFunc сначала чем-то другим:

init() {
    outputFunc = {_ in}
    outputFunc = methodA
}

Лично я действительно не думаю, что есть какая-либо опасность, позволяющая вам присвоить метод свойству, когда класс / структура не инициализированы должным образом. Это ограничение предотвращает подобные вещи (надуманный пример):

class Foo {
    var foo = f() // foo's value should be the return value of f...
    func f() -> Int {
        print(foo) // but to execute f, we need the value of foo...
        return foo + 1 // so what is the value of foo?
    }
}

Но поскольку вы на самом деле не звоните methodA, я не понимаю, как это назначение может вызвать проблемы. Я предполагаю, что они просто запретили все варианты использования self, не допуская исключений, потому что это проще реализовать таким способом.

...