Быстрые ограничения типа расширения - PullRequest
1 голос
/ 12 февраля 2020

XCode 11.2.1 macOS Mojave 10.14.6

Итак, я пытаюсь добавить возможность удалять объекты из массива, если я сохранил ссылку. Следуя совету inte rnet, я заставил мой протокол наследоваться от AnyObject, так как это вызывает / требует / подразумевает, что === будет определено во всех классах, которые реализуют протокол. Однако XCode ведет себя странно с типами в расширении Array. Считайте, что следующие компиляции нормально:

public protocol Foo: AnyObject {
}

public extension Array where Element == Foo {
    mutating func removeElement(element: Element) {
        if let idx = self.firstIndex(where: {$0 === element}) {
            self.remove(at: idx)
        }
    }
}

public func bar(array: [Foo], element: Foo) -> [Foo] {
    var arrayCopy: [Foo] = array
    arrayCopy.removeElement(element: element)
    return arrayCopy
}

, но если я изменю тип расширения на Element: AnyObject, я получу ошибку компиляции следующим образом:

...
public extension Array where Element: AnyObject {
...
...
    // Compiler error: '[Foo]' requires that 'Foo' conform to 'AnyObject'
    arrayCopy.removeElement(element: element)
...

Foo DOES соответствовать AnyObject. Это прямо в своем определении. Почему XCode не подтверждает это?

1 Ответ

0 голосов
/ 12 февраля 2020

Вы используете старое программное обеспечение, поэтому вы не получаете современного сообщения об ошибке:

Ссылка на метод экземпляра 'removeElement (element :)' на 'Array' требует, чтобы 'Foo' был классом типа

И это правда. element не является экземпляром типа stati c, насколько понимает компилятор, но будет, если вместо этого вы напишите его так:

public func bar<Foo: Module.Foo>(array: [Foo], element: Foo) -> [Foo] {

где Module конечно же, это фактическое имя вашего модуля.


Если вам нужно использовать гетерогенный массив, тогда я не знаю, как сделать вещи чище, чем эта. Дайте мне знать, если вы поймете лучше.

(оставьте сигнатуру функции неизменной; вместо этого измените тело.)

var arrayCopy: [AnyObject] = array
arrayCopy.removeElement(element: element)
return arrayCopy as! [Foo]
...