Невозможно объявить расширение публичного протокола с внутренними требованиями
Я программирую приложение для медиаплеера и создал собственную структуру для управления всеми функциями плеера. В этом контексте у меня есть публичный протокол под названием PlayerControllerType
и внутренний протокол _PlayerControllerType
, В PlayerControllerType
Я объявил все методы и свойства, которые должны быть доступны извне. В _PlayerControllerType
Я определил пару свойств, которые используются конкретными типами, реализующими PlayerControllerType
внутри рамок. Один из этих типов PlayerController
, Его декларация выглядит следующим образом:
public class PlayerController<Item: Equatable>: NSObject, PlayerControllerType,
_PlayerControllerType, QueueDelegate
Теперь я хочу предоставить пару реализаций по умолчанию для классов в моей среде, которые соответствуют PlayerControllerType
и внутренний _PlayerControllerType
, например:
import Foundation
import MediaPlayer
public extension PlayerControllerType where Self: _PlayerControllerType, Item == MPMediaItem, Self.QueueT == Queue<Item>, Self: QueueDelegate {
public func setQueue(query query: MPMediaQuery) {
queue.items = query.items ?? []
}
}
Это работает, как и ожидалось в Xcode 7 Beta 4. Вчера я обновился до Beta 6 и получил эту ошибку: "Расширения не могут быть объявлены общедоступными, поскольку их общее требование использует внутренний тип" (также см. Скриншот).
Я нахожу эту ошибку раздражающей. Конечно, никакой тип за пределами моей структуры не имеет преимущества этого расширения, потому что оно не может получить доступ к внутреннему протоколу. _PlayerControllerType
, но это очень полезно для типов внутри моей структуры, которые реализуют оба PlayerControllerType
а также _PlayerControllerType
,
Это просто ошибка в компиляторе Swift или это предполагаемое поведение? Очень жаль, что это больше не работает, потому что теперь я должен поместить эти методы во вновь созданный базовый класс для всех моих PlayerControllers.
Любая помощь или обратная связь будет принята с благодарностью.
Кай
РЕДАКТИРОВАТЬ: Вот сокращенный пример протоколов и их расширений:
public protocol PlayerControllerType {
typealias Item
var nowPlayingItem: Item {get}
func play()
}
protocol _PlayerControllerType {
var nowPlayingItem: Item {get set}
}
public extension PlayerControllerType where Self: _PlayerControllerType {
/*
I want to provide a default implementation of play() for
all my PlayerControllers in my framework (there is more than one).
This method needs to be declared public, because it implements a
requirement of the public protocol PlayerControllerType.
But it cannot be implemented here, because this extension
has the requirement _PlayerControllerType. It needs this requirement,
because otherwise it cannot set the nowPlayingItem. I don't want to
expose the setter of nowPlayingItem.
I could make a base class for all PlayerControllers, but then I'm
restricted to this base class because Swift does not support
multiple inheritance.
*/
public func play() {
if nowPlayingItem == nil {
nowPlayingItem = queue.first
}
// Other stuff
}
}
1 ответ
Вы должны объявить уровень доступа _PlayerControllerType
протокол как " публичный ".
public protocol _PlayerControllerType {
// some code
}
Согласно ( Язык программирования Swift - Контроль доступа),
Открытые члены не могут быть определены как имеющие внутренний или закрытый тип, потому что тип может быть недоступен везде, где используется открытая переменная. Классы объявлены как внутренние по умолчанию, поэтому вы должны добавить ключевое слово public, чтобы сделать их общедоступными.
Член (класс / протокол / функция / переменная) не может иметь более высокий уровень доступа, чем его типы параметров и тип возвращаемого значения, поскольку функция может использоваться в ситуациях, когда ее составные типы недоступны для окружающего кода.