Подтвердить что ты не робот

Связанное значение в условной привязке должно быть необязательного типа

У меня установлен протокол:

protocol Usable {
    func use()
}

и класс, соответствующий этому протоколу

class Thing: Usable {
    func use () {
        println ("you use the thing")
    }
}

Я хотел бы программно проверить, соответствует ли класс Thing протоколу Usable.

let thing = Thing()

// Check whether or not a class is useable
if let usableThing = thing as Usable { // error here
    usableThing.use()
}
else {
    println("can't use that")
}

Но я получаю ошибку

Bound value in a conditional binding must be of Optional Type

Если я попробую

let thing:Thing? = Thing()

Я получаю сообщение об ошибке

Cannot downcast from 'Thing?' to [email protected] protocol type 'Usable'

Затем я добавляю @objc в протокол и получаю сообщение об ошибке

Forced downcast in conditional binding produces non-optional type 'Usable'

В какой момент я добавляю ? после as, который, наконец, исправляет ошибку.

Как я могу достичь этой функциональности с условной привязкой к протоколу non @objc, так же, как в видеоролике "Advanced Swift" 2014 WWDC?

4b9b3361

Ответ 1

Вы можете заставить его скомпилировать, сделав актер подходящим для использования? а не как Usable, например:

// Check whether or not a class is useable
if let usableThing = thing as Usable? { // error here
    usableThing.use()
}
else {
    println("can't use that")
}

Ответ 2

Как указано в документе Swift, оператор is - это парень, который вам нужен для работы:

Оператор is проверяет во время выполнения, чтобы узнать, имеет ли выражение выражение указанный тип. Если это так, он возвращает true; в противном случае возвращается ложь.

Проверка не должна быть достоверной или ложной во время компиляции.

Следовательно, следующий тест обычно будет тем, что вам нужно:

if thing is Usable { 
    usableThing.use()
} else {
    println("can't use that")
}

Однако, как указывает doc, Swift может во время компиляции обнаруживать, что выражение всегда истинно и объявляет ошибку, чтобы помочь разработчику.

Ответ 3

Это работает для меня на игровой площадке

protocol Usable {
    func use()
}

class Thing: Usable {
    func use () {
        println ("you use the thing")
    }
}

let thing = Thing()
let testThing : AnyObject = thing as AnyObject

if let otherThing = testThing as? Thing {
    otherThing.use()
} else {
    println("can't use that")
}

Ответ 4

Вы получаете

Bound value in a conditional binding must be of Optional Type

потому что thing as Usable должен возвращать необязательный тип, поэтому его as? должно решить проблему. К сожалению, ошибка по-прежнему сохраняется по какой-то нечетной причине. Во всяком случае, обходной путь, который я нашел, чтобы заставить его работать, состоит в том, чтобы извлечь назначение переменной внутри оператора if

let thing = Thing()

let usableThing = thing as? Usable

if useableThing { 
    usableThing!.use()
}
else {
    println("can't use that")
}

Ответ 5

быстрые протоколы не работают в Playgrounds в первой бета-версии, попробуйте вместо этого создать реальный проект.