Я написал код, который, по моему мнению, должен работать в Swift 2 (Xcode 7b4), но он не компилируется. Я надеюсь получить некоторые мысли о том, должно ли то, что я пытаюсь сделать, быть действительным.
Рассмотрим этот пример расширения Array
:
extension Array where Element: AnyObject {
mutating func appendUniqueInstance(e: Element) {
for element in self {
if (element === e) {
return
}
}
self.append(e)
}
}
Во-первых, что я имею в виду под массивом, элементами которого являются AnyObject
? По сути, я говорю, что массив должен содержать разнородную группу объектов, не относящихся к типу значения, которые можно сравнивать на предмет равенства экземпляров (===
).
Пример функции appendUniqueInstance()
вставляет элемент в массив только в том случае, если его еще нет в массиве. Это похоже на операцию Set
insert()
, но, очевидно, обеспечивает упорядочение и (что более важно) не налагает требования однородного типа Set
(через Equatable
использование Self
).
Если я сейчас определяю протокол P
и класс C
, который реализует P
:
protocol P : AnyObject {}
class C : P {}
и создайте экземпляр C
:
let c = C()
Тогда эти очень очевидные вещи верны:
let cIsAnyObject = c as AnyObject // ok
let cIsP = c as P // ok
И теперь я могу сделать следующее:
var a1 = [AnyObject]() // []
a1.appendUniqueInstance(c) // [c]
a1.appendUniqueInstance(c) // [c]
Пока все хорошо, а теперь о проблемном случае:
var a2 = [P]()
a2.append(c) // ok, -> [c]
// Compiler error: Cannot invoke 'appendUniqueInstance' with an argument list of type '(C)'
a2.appendUniqueInstance(c)
Здесь a2
вводится как массив P
, поэтому должно быть вполне допустимо сделать с append
экземпляр P
, и действительно строка a2.append(c)
работает так, как мы и ожидали.
Однако вызов функции расширения Array
appendUniqueInstance()
вызывает ошибку компилятора.
Насколько я могу судить, компилятор, кажется, запутался в том, что может быть передано в appendUniqueInstance()
, и не понимает (или допускает по какой-то причине), что C
(через P
) является AnyObject
.
Кстати, если я объявлю P
вместо этого как:
@objc protocol P : AnyObject {}
тогда все компилируется просто отлично, но я также должен убедиться, что все в протоколе P
соответствует @objc
, а это не то, что я хочу.
Итак, после всего этого у меня вопрос: похоже ли это на то, что должно работать? Я надеюсь, что это не просто случай неправильного синтаксиса объявления, но, думаю, я буду рад, если это так.