То, что вы ищете, будет «защищенным» уровнем, которого нет в Swift и не может существовать без создания нового уровня защиты, поскольку это нарушит оптимизацию компилятора. В вашем примере, поскольку обещано, что getPermission(forFeature:)
никогда не будет вызываться за пределами этой области, компилятор может встроить его. Таким образом, эта функция может даже не существовать в том месте, где ваше расширение хочет ее вызвать.
Swift может добавить «защищенный» уровень, который является «semi-publi c», но Swift нет такой функции. Чтобы это стало возможным, вам потребуется переработать FeatureDataManager. Из вашего примера не очевидно, как это сделать, потому что вы вообще не предоставляете интерфейс publi c для разрешений, поэтому неясно, что вы имеете в виду под «Я хочу иметь возможность расширить его, чтобы создать более значимое имя метода. " В настоящее время отсутствует no publi c имя метода. Если бы он был, то сделать более удобный синтаксис, как вы описали, было бы легко.
Не могли бы вы привести пример вызывающего кода, который вы хотите улучшить с помощью этого расширения?
Подробнее почему язык такой, см. Контроль доступа и защищенный . Это не случайно.
Вы заметили, что это можно сделать в том же файле, и это правда. Swift допускает это по причинам стилистического c (многие люди используют расширения внутри одного файла по причинам организации кода). Swift рассматривает все расширения в одном файле как находящиеся в основном определении. Но это не распространяется на другие файлы и, конечно, не на другие модули.
Общее c решение этого выглядит следующим образом:
public class FeatureDataManager<Feature>
where Feature: RawRepresentable, Feature.RawValue == String {
private func getPermission(forFeature feature: String) -> Bool { ... }
public func isPermissionEnable(forFeature feature: Feature) {
self.getPermission(forFeature: feature.rawValue)
}
}
Приложение затем создаст набор функций и создайте менеджера для этого набора функций:
enum AppFeature: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
let featureDataManager = FeatureDataManager<AppFeature>()
featureDataManager.isPermissionEnable(forFeature: .ads)
Это мешает простому созданию экземпляра .shared
. Спорный вопрос, хорошо это или плохо, но если предположить, что вы этого хотите, вам нужно будет обернуть это:
class AppFeatureDataManager {
enum Feature: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
static var shared = AppFeatureDataManager()
let manager = FeatureDataManager<Feature>()
public func isPermissionEnable(forFeature feature: Feature) {
manager.isPermissionEnable(forFeature: feature)
}
}
Теперь это слишком много шаблонов для стороны приложения (особенно если существует больше методов, чем isPermissionEnable
), поэтому вы можете удалить шаблон следующим образом (полный код):
public class FeatureDataManager<Feature>
where Feature: RawRepresentable, Feature.RawValue == String {
private var permissionManager: PermissionManager
init() {
self.permissionManager = PermissionManager()
}
private func getPermission(forFeature feature: String) -> Bool {
self.permissionManager.isEnable(feature)
}
public func isPermissionEnable(forFeature feature: Feature) {
self.getPermission(forFeature: feature.rawValue)
}
}
protocol AppFeatureDataManager {
associatedtype Feature: RawRepresentable where Feature.RawValue == String
var manager: FeatureDataManager<Feature> { get }
}
// Here you can write any necessary pass-through functions so the app doesn't have to
extension AppFeatureDataManager {
public func isPermissionEnable(forFeature feature: Feature) {
manager.isPermissionEnable(forFeature: feature)
}
}
//
// Application Developer writes this:
//
class MyGreatAppFeatureDataManager {
enum Feature: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
// This is the only thing that's really required
let manager = FeatureDataManager<Feature>()
// They're free make this a shared instance or not as they like.
// That's not something the framework cares about.
static var shared = MyGreatAppFeatureDataManager()
private init() {}
}
С учетом всего сказанного, я думаю, что получается слишком много слоев, если FeatureDataManager на самом деле это просто интерфейс для PermissionManager, как вы описали здесь. (Возможно, ваш пример сильно упрощен, поэтому приведенный ниже пример неприменим.)
Если PermissionManager - publi c, и настоящая цель состоит в том, чтобы иметь для него более приятный интерфейс, я бы написал это так:
protocol FeatureDataManager {
associatedtype Feature: RawRepresentable where Feature.RawValue == String
var permissionManager: PermissionManager { get }
}
extension FeatureDataManager {
func isPermissionEnable(forFeature feature: Feature) {
permissionManager.isEnable(feature.rawValue)
}
}
//
// App developer writes this
//
class MyGreatAppFeatureDataManager: FeatureDataManager {
enum Feature: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
// This is the only required boilerplate; the protocol can't do this for you.
let permissionManager = PermissionManager()
// And the developer can decide to make it a shared instance if they like,
// but it's not the business of the framework
static let shared = MyGreatAppFeatureDataManager()
private init() {}
}