Является ли константа Swift String другого типа, чем строковый литерал?
В Swift 2.1 фрагмент ниже генерирует ошибку.
var str = "Hello, playground!"
// Success Case
if "!" == str.characters.last {
print("Tone it down please")
}
// Fail Case
let bang = "!"
if bang == str.characters.last { // this line won't compile
print("Tone it down please")
}
Ошибка компилятора говорит:
Двоичный оператор '==' нельзя применить к операндам типа 'String' и '_Element?'
Итак, каков рекомендуемый способ использования константы, а не литерала в этой ситуации? (Я изучаю Swift, поэтому, пожалуйста, не стесняйтесь упоминать, есть ли способ Swift-er для обработки такого рода сравнительной проверки.)
Спасибо!
4 ответа
Для вашего "случая провала" это потому, что str.characters.last
является необязательным и является Character
, но bang
это String
,
Вы можете безопасно развернуть и сравнить с if let ... where
и использовать String()
изменить Character
к String
для сравнения:
if let last = str.characters.last where String(last) == bang {
print("Tone it down please")
}
Как говорит ошибка, первый оператор String
и второй является необязательным Character
,
Но вы уже продемонстрировали, что знаете, как превратить строку в Character?
так что давайте использовать это:
if bang.characters.last == str.characters.last {
print("Tone it down please")
}
Ты знаешь что bang.characters.last
просто вернусь "!"
, но теперь он будет того же типа, что и str.characters.last
так что будет несложно их сравнить.
Спасибо за хорошее обсуждение. Вот мой собственный ответ, чтобы улучшить иллюстрацию путем исключения посторонних опций и продемонстрировать как хорошие, так и плохие выводы типа в игре:
let a:String = "!" // type is String
let b:Character = "!" // type is Character
let c = "!".characters.last! // type is _Element
let bang = "!" // inferred type is String
if "!" == a { print("literal matches string") }
if "!" == b { print("literal matches Character") }
if "!" == c { print("literal matches _Element") }
if a == b { print("a matches b") } // Err: 'String' to 'Character'
if a == c { print("a matches c") } // Err: 'String' to '_Element'
if b == c { print("b matches c") } // OK: 'Character' to '_Element'
Вывод: литерал, состоящий из одного символа в кавычках, может быть распознан как String
или как Character
(или эквивалентно _Element
), если контекст подсказывает это.
Важно: тип константы постоянно устанавливается при ее объявлении. Тип литерала выводится из его контекста, поэтому один и тот же литерал может иметь разные типы в разных контекстах.
Гибкий вывод типа, предоставленный литералу, не доступен с константой.
Не уверен, что это полностью связано, но я нашел этот пост, так как у меня были проблемы с конвертацией между characters.first
, characters.last
а также Int
,
На случай, если это кому-нибудь поможет:
let element = characters.first! // the ! is important
let myString = String(element)
let myInt = Int(myString) // may be nil if character is not an int