Преобразовать переменную неопределенного типа c в строку, если это возможно - PullRequest
0 голосов
/ 22 января 2020

Я пишу программу, использующую много классов, и большинство этих классов имеют специальные переменные, которые преобразуются в строку особым образом, и все они определены в .toString() в своем классе. У меня есть [Any], называемый term, содержащий множество неспецифических c предметов. Я хочу преобразовать их все в строку и добавить их в строку с именем formatted.

Это что-то вроде того, чего я хочу достичь:

for item in term as! [Any] {
            formatted += item.toString()
        }

Конечно, это не работает, так как Any не имеет toString(). Есть ли способ добавить toString(), если в классе моего объекта есть метод toString(), а если нет, просто сделать что-то вроде добавления пустой строки для этого объекта или вернуть сообщение об ошибке?

Ответы [ 3 ]

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

Одной из возможностей является протокол. Вы можете объявить протокол (давайте назовем его Stringable), который требует метод toString, и заставить все эти классы / типы принять протокол. Теперь вам гарантировано, что если класс / тип соответствует этому протоколу, он имеет метод toString. Если у вас есть массив Stringable, вы можете отправить toString любому элементу этого массива.

Однако обычно это не так. toString не Swifty. Swift преобразует в строку, говоря String(whatever) или String(describing:whatever). Все встроенные типы позволяют вам это делать. Вы можете добавить свои собственные типы, расширив тип String инициализаторами для вашего типа. Или объявите соответствие CustomStringConvertible и реализуйте description.

По сути, вы заново изобретаете колесо. Swift хочет, чтобы вы могли представлять любой тип в виде строки. Методы типа toString звучат так, как будто они типичны для какого-то другого языка (Ruby?) И не являются быстрым способом. Метод String(describing:) уже существует и готов представить ваш экземпляр в виде строки. И массивы Any неестественны в Swift и почти никогда не должны использоваться.

1 голос
/ 22 января 2020

Другой вариант - пропустить функцию toString() и позволить классам / структурам, которые ее реализовали, вместо этого соответствовать CustomStringConvertible и добавить взамен требуемое вычисляемое свойство description, но с тем же кодом, что и toString

То есть

func toString() -> String {
    //some code
}

будет

var description: String {
    get {
        //some code
    }
}

В зависимости от того, как определяется и используется ваш массив term, вы можете либо переопределить его как

var term: [CustomStringConvertible]

если все элементы будут соответствовать протоколу, а затем выполните

for item in term {
    formatted += item.description
}

Если вы не хотите изменять определение, вы можете попробовать привести каждый элемент

for item in term2 {
    if let item = item as? CustomStringConvertible {
        formatted += item.description
    } else {
        formatted += String(describing: item)
    }
}
0 голосов
/ 23 января 2020

есть много опций, стандарт соответствует надлежащим быстрым протоколам

struct S {
    let a: Int
}

let s = S(a: 1)
print(s, String(describing: s), String(reflecting: s))

extension S: TextOutputStreamable {
    func write<Target>(to target: inout Target) where Target : TextOutputStream {
        target.write("TextOutputStreamable")
    }
}

extension S: CustomStringConvertible {
    var description: String {
        "CustomStringConvertible"
    }
}

extension S: CustomDebugStringConvertible {
    var debugDescription: String {
        "CustomDebugStringConvertible"
    }
}

результат печати показывает, как различные протоколы имеют приоритет

TextOutputStreamable CustomStringConvertible CustomDebugStringConvertible

удаляет расширения и печатает

S(a: 1) S(a: 1) __lldb_expr_1.S(a: 1)

удалить расширения один за другим и посмотреть ...: -)

что насчёт Any?

let a: Any = s
print(a, String(describing: a), String(reflecting: a))

отпечатков

TextOutputStreamable TextOutputStreamable CustomDebugStringConvertible

давайте попробуем [Any]

print([a], String(describing: [a]), String(reflecting: [a]))

, и результат будет

[CustomDebugStringConvertible] [CustomDebugStringConvertible] [CustomDebugStringConvertible]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...