Тип расширения протокола Self не соответствует типам инициализатора

Скажем, для академических целей я бы предпочел выражение вроде

someInt.asDouble

а не акции

Double(someInt)

Поскольку все различные целые типы Swift соответствуют протоколу IntegerType И поскольку, похоже, существует инициализатор Double(), который подходит для всех типов этих типов int, я подумал, что мог бы что-то вроде:

extension IntegerType {
    var asDouble:Double {
        return Double(self)
    }
}

Это не работает. И я хотел бы знать, почему? Я хотел бы знать, есть ли какое-то волшебство, которое заставит это работать? Может where? Или как-то связано со ссылкой self?

Ошибка, которую я получаю в консоли игровой площадки, которую я пробовал, гласит:

Playground execution failed: /var/folders/2k/6y8rslzn1m95gjpg534j7v8jzr03tz/T/./lldb/41416/playground37.swift:31:10: error: cannot invoke initializer for type 'Double' with an argument list of type '(Self)'
                return Double(self)
                       ^
/var/folders/2k/6y8rslzn1m95gjpg534j7v8jzr03tz/T/./lldb/41416/playground37.swift:31:10: note: overloads for 'Double' exist with these partially matching parameter lists: (Double), (UInt8), (Int8), (UInt16), (Int16), (UInt32), (Int32), (UInt64), (Int64), (UInt), (Int), (Float), (Float80), (String), (CGFloat), (NSNumber)
                return Double(self)

person Travis Griggs    schedule 11.11.2015    source источник
comment
Если бы вы были компилятором, как бы вы узнали, какая версия верна? это невозможно. вокруг много подобных вопросов. наша проблема состоит в том, чтобы понять, что быстрый тип это безопасный язык....   -  person user3441734    schedule 11.11.2015
comment
Int — это то, что содержит значение. Ни один из протоколов, которым он соответствует.   -  person R Menke    schedule 11.11.2015
comment
@RMenke Означает ли это, что расширение протокола не может ссылаться на self?   -  person Travis Griggs    schedule 11.11.2015


Ответы (1)


Все типы IntegerType можно повысить до IntMax, а IntMax можно преобразовать в Double.

extension IntegerType {
    var asDouble: Double {
        return Double(self.toIntMax())
    }
}

Как вы предполагаете, это не особенно полезно (Double(x) - правильный синтаксис), но может быть полезно для других проблем.

Я бы продолжил шаблон stdlib, если бы собирался создать это. Шаблон toX(), а не asX:

extension IntegerType {
    func toDouble() -> Double {
        return Double(self.toIntMax())
    }
}

См. также toOpaque() и toUIntMax(). as предполагает простую переинтерпретацию типа без копирования, а var предполагает, что это свойство этого значения. Это не то, что происходит. На самом деле вы конвертируете его в другое значение, хранящееся в другом формате, которое может даже не быть равным. (Для больших целых чисел могут быть ошибки округления, такие как x != Int(x.toDouble()).)

Также стоит прочитать Попытка расширить IntegerType (и FloatingPointType); Почему не все типы Int могут быть преобразованы в NSTimeInterval, в котором обсуждается проблема, а также почему подобные функции могут быть опасными, если они не выполняются с большой осторожностью.

person Rob Napier    schedule 11.11.2015
comment
@Rob Napier отлично!! действительно очень полезный ответ !! - person user3441734; 12.11.2015
comment
@Rob Napier, как быть с FloatingPointType ?? - person user3441734; 12.11.2015
comment
См. stackoverflow.com/questions/33620967/. Весь этот подход довольно бесполезен, так как Double(x) в этом случае, безусловно, является лучшим решением, и я даю лучшее решение для NSTimeInterval внизу связанного ответа. Но теоретически он может быть полезен для чего-то другого, что превышает его опасность. (Я также объясняю опасности в связанном ответе.) - person Rob Napier; 12.11.2015
comment
@Rob Napier, мне нужна «универсальная» версия математических функций. в стандартной библиотеке есть, например, round(Double), round(Float).... мне нормально сначала конвертировать все в Double, но я понятия не имею как. существует что-то похожее на .toIntMax() для FloatingPointType??? - person user3441734; 13.11.2015
comment
См. ранее связанный вопрос (последний абзац выше). Я предоставляю там протокол TimeIntervalConvertible. DoubleConvertible будет идентичным. Я также объясню, почему преобразование в Double — это не то же самое, что преобразование в IntMax, поэтому нужно соблюдать осторожность. - person Rob Napier; 13.11.2015