#swift
Вопрос:
Я хотел преобразовать тип значения, соответствующий BinaryFloatingPoint, в строку, но я заметил, что для этого нет инициализатора, доступного в xCode! Я использовал "()"
в этом нижнем коде, но я знаю, что это единственный способ преобразования?
func test<T: BinaryFloatingPoint>(value: T) {
let stringValue: String = "(value)"
print(stringValue)
}
С другой стороны, я попытался преобразовать двоичный регистр в строку, я узнал, что для этого есть инициализатор, но я подумал, зачем нам вообще нужен этот инициализатор? потому что мы могли бы использовать "()"
и здесь, не беспокоясь о том, есть или нет инициализатора!
func test<T: BinaryInteger>(value: T) {
let stringValue: String = String(value)
print(stringValue)
}
Цель: Итак, я хочу знать, зачем нам нужен инициализатор строк, когда мы могли бы преобразовать почти все с "()"
помощью ?
Комментарии:
1. Не каждый тип может быть инициализатором со строковым инициализатором. Попробуйте изменить BinaryInteger на BinaryFloatingPoint
2. @LeoDabus: когда мы не можем инициализировать строкой, что нам тогда делать?
Ответ №1:
Нет, это не единственный способ его преобразования. Вы можете добавить еще одно ограничение к вашему универсальному типу, требующее, чтобы LosslessStringConvertible
он также соответствовал. Обратите внимание, что все BinaryFloatingPoint
типы соответствуют CustomStringConvertible
, но не все из них соответствуют LosslessStringConvertible
(т. е. CGFloat).
Если вас не волнует поддержка вашего метода CGFloat
, вы можете ограничить его LosslessStringConvertible
, в противном случае вам нужно использовать CustomStringConvertible
String(describing:)
инициализатор.
Это не будет поддерживать CGFloat
func test<T: BinaryFloatingPoint amp; LosslessStringConvertible>(value: T) {
let stringValue = String(value)
print(stringValue)
}
Это будет поддерживать все BinaryFloatingPoint
типы с плавающей запятой. Обратите внимание, что вам не нужно ограничиваться CustomStringConvertible
этим . Это только в демонстрационных целях.
func test<T: BinaryFloatingPoint amp; CustomStringConvertible>(value: T) {
let stringValue = String(describing: value)
print(stringValue)
}
Вы также можете сделать CGFloat
так, чтобы соответствовать LosslessStringConvertible
:
extension CGFloat: LosslessStringConvertible {
private static let formatter = NumberFormatter()
public init?(_ description: String) {
guard let number = CGFloat.formatter.number(from: description) as? CGFloat else { return nil }
self = number
}
}
Это позволит вам поддерживать все типы с плавающей запятой с помощью вашего универсального метода, а также использовать инициализатор строк.
Ответ №2:
Я хочу знать, зачем нам нужен инициализатор строк, когда мы могли бы преобразовать почти все с помощью
"()"
Спросите себя, что "()"
делает. По умолчанию он вызывает инициализатор! Именно String(describing:)
. Это, в свою очередь, зависит от настраиваемой конвертируемой и т. Д. Видишь https://developer.apple.com/documentation/swift/string/2427941-init
Комментарии:
1. Нет!, нет описания, доступного для BinaryFloatingPoint, также нет инициализатора, доступного для BinaryFloatingPoint для строки! но все равно
"()"
можно преобразовать его без доступа к описанию или какому-либо инициализатору. Я думаю, что есть еще кое-что, что происходит с"()"
2. Прочтите документы, на которые ссылался Мэтт. Он включает в себя различные шаги, в том числе «стандартная библиотека Swift автоматически выдает неопределенный результат», что выполняется для типов, которые не соответствуют ни одному из доступных протоколов. Но тебе не нужно гадать. Вы можете прочитать источник stdlib для этой функции. Если вы отследите его, он будет обработан
_adHocPrint_unlocked()
: github.com/apple/swift/blob/main/stdlib/public/core/…3. Если вы хотите точно увидеть, как реализована интерполяция строк, см. github.com/apple/swift/blob/main/stdlib/public/core/…