Связанное значение в условной привязке должно быть необязательного типа
У меня установлен протокол:
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?
Ответы
Ответ 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 в первой бета-версии, попробуйте вместо этого создать реальный проект.