Возвращение зависящего от времени выполнения Generi c в Swift - PullRequest
0 голосов
/ 28 февраля 2020

Я хочу определить метод, который возвращает обобщенный c класс в зависимости от внутренней конфигурации класса.

Например:

class MyClass {

    private var returnString: Bool

    func array<E>() -> Array<E> {
        if returnString {
            return ["Hello World"] as! [E]
        } else {
            return [1] as! [E]
        }
    }

    func changeThings() {
        returnsString = !returnsString
    }

    init(returnString: Bool) {
        self.returnString = returnString
    }

}

let myClass = MyClass(returnString: true)
let myStrings = myClass.array() // Generic parameter 'E' could not be inferred

Как мне сделать sh такой вещь, только в рабочей версии. Я предполагаю, что Generics - не путь к go, так как мой вариант использования требует оценки времени выполнения? Любой способ, которым я мог бы использовать type (of :) и такие вещи?

Моя цель состоит в том, чтобы иметь «чистый» API с безопасным типом array() вызовом, где [E] может быть выведен, как это:

let myStrings = myClass.array()

1 Ответ

1 голос
/ 28 февраля 2020

Это неправильное понимание того, что такое дженерики. Эта строка кода не делает то, что вы ожидаете:

func array<E>() -> Array<E>? {

Это говорит, что "для любого типа, переданного вызывающей стороной, эта функция возвратит необязательный массив этого тип." Независимо от типа. Ваша функция возвращает [String]? или [Int]?, которые являются только двумя возможными типами. Ваша функция обещала, что может обработать что угодно .

Типы - это обещания, и вам нужно сдержать свое обещание здесь. У вас есть функция, которая возвращает либо массив строк или массив Int. Вы можете express "либо", используя перечисление:

enum ReturnType {
    case string([String])
    case int([Int])
}

И тогда ваша функция возвращает:

func array() -> ReturnType {
    if returnString {
        return .string(["Hello World"])
    } else {
        return .int([1])
    }
}

И ваш вызывающий код получает .string(["Hello World"]):

let myClass = MyClass(returnString: true)
let myStrings = myClass.array()

Если вместо myStrings иногда [String], а иногда [Int], что будет делать строка кода myStrings[0].count (в Int нет .count)? Должно ли оно взломать sh? Весь смысл типов * stati c состоит в том, чтобы определить, является ли что-то безопасным во время компиляции, а не просто сбой во время выполнения.

Вы также можете изменить свое обещание. Например, вы можете сказать «это возвращает массив вещей, которые могут быть преобразованы в строки».

func array() -> [CustomStringConvertible] {
    if returnString {
        return ["Hello World"]
    } else {
        return [1]
    }
}

И тогда вы можете смело вызывать description для результатов. Или вы можете назначить свой собственный протокол, обеспечивающий любые необходимые вам функции.

...