Как добавить условие ИЛИ в предложение Swift generic where? - PullRequest
0 голосов
/ 10 июня 2018

Я расширяю SCNVector3 от Apple SceneKit с помощью арифметических операций с числом.Я использую универсальный тип номера, но я обнаружил, что мне нужно написать как минимум две версии каждой функции, так как это не работает:

extension SCNVector3 {
    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 {
        return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))
}

и выдает ошибку Невозможно вызвать инициализатордля типа 'Float' со списком аргументов типа '(T)'

Глядя на определение Float в документации Apple, я вижу, что наиболее универсальный, который я могу получить, этоinit<Source: BinaryFloatingPoint> или init<Source: BinaryInteger>.

Поэтому мне нужно переписать расширение следующим образом, сделав две почти идентичные функции для каждой операции:

extension SCNVector3 {
    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryFloatingPoint {
        return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))

    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryInteger {
        return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))
}

Я могу поместить AND в whereпредложение - наличие двух условий после where, разделенных запятой.

Но есть ли способ, которым я могу поместить ИЛИ там?

1 Ответ

0 голосов
/ 10 июня 2018

Ваша базовая реализация должна начинаться с этого:

extension SCNVector3 {
    static func * (vector: SCNVector3, scale: Float) -> SCNVector3 {
        return SCNVector3(vector.x * scale, vector.y * scale, vector.z * scale)
    }
}

Вектор содержит Float компонентов, поэтому вы всегда должны умножаться только на Float.Так работают все операторы в Swift.Если у вас другой тип, приведите его перед умножением, а не как побочный эффект умножения.

Если вы действительно хотите передать другие типы, то вы можете использовать перегрузку метода:

extension SCNVector3 {
    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryFloatingPoint {
        return left * Float(right)
    }

    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryInteger {
        return left * Float(right)
    }
}

Нет способа определить или в типах.

...