При реализации статической функции протокола, возвращающей Self
в расширении протокола, при реализации функции в расширении появляется ошибка (минимальный упрощенный сценарий показан без контекста):
import Foundation
protocol P {
static func f() -> Self
static func g() -> Self
}
extension P {
static func f() -> Self { // Method 'f()' in non-final class 'NSData' must return 'Self' to conform to protocol 'P'
return g()
}
}
extension NSData: P {
static func g() -> Self {
return self.init()
}
}
Замена Self
на P
в строке, в которой произошла ошибка, приводит к тому, что компилятор вызывает ошибку (рис. 11) (что, по-видимому, является допустимым способом передачи ошибки несоответствия типов).
Изменение объявления функции f()
для возврата P
, а также замена Self
на P
в строке ошибки приводит к успешной компиляции, однако теряет точность типа (и требует принудительного даункастинга на каждом сайте вызовов, а также подробно документирует требование Self
),
Существуют ли другие обходные пути для этой проблемы, которые не теряют универсальный тип возвращаемого значения?
РЕДАКТИРОВАТЬ: Дополнительные сведения, чтобы компенсировать отсутствие контекста: P
- это публичный протокол, который будет предоставлен библиотекой для соответствия различных типов (и переопределения g()
), поэтому переопределение f()
в NSData
не вариант. Также предпочтительно не менять f()
на что-то, кроме расширения протокола, так как оно используется библиотекой внутри во многих местах. Учитывая эти две опции, изменение типа возврата f()
на P
является лучшей альтернативой.
Обновить
Начиная с Swift 4 (возможно, 3), приведенный выше код работает как есть.