使函数只能从一个 class 调用
Make function only callable from one class
我有一个 class LoggingManager
和一个协议 LoggingHandler
,只有一个方法 send(LoggingEvent)
。
LoggingManager
保留 LoggingHandler
的列表。
我希望 LoggingManager
成为允许从 LoggingHandler 和使用该协议的 classes 调用 send(LoggingEvent)
的 only class应该实现 send(LoggingEvent)
方法。
我尝试将 LoggingHandler
和 LoggingManager
放入同一个文件并将 send(LoggingEvent)
标记为 fileprivate。
但是,它在协议中是不允许的。
有没有办法让它起作用?
LoggingManager.swift
import Foundation
public struct LoggingEvent {
var eventName: String
var eventParams: [String: Any]
public init(_ name: String, _ eventParams: [String: Any]) {
self.eventName = name
self.eventParams = eventParams
}
public init(_ name: String) {
self.eventName = name
eventParams = [String: Any]()
}
mutating public func addParameter(_ eventName: String, _ eventValue: Any) {
self.eventParams[eventName] = eventValue
}
}
public protocol LoggingHandler {
func logEvent(_ event: LoggingEvent) ///<--- Only LoggingManager should call this function, but classes implementing this should override it
}
public class LoggingManager {
private var loggingHandlers: [LoggingHandler]
static let shared = LoggingManager()
private init() {
loggingHandlers = []
}
public func registerLoggingHandler(_ loggingHandler: LoggingHandler) {
loggingHandlers.append(loggingHandler)
}
public func logEvent(_ event: LoggingEvent) {
for handler in loggingHandlers {
handler.logEvent(event)
}
}
}
FirebaseLogger.swift
class FirebaseLogger: LoggingHandler {
var firebaseApp: FirebaseApp?
public init() {
FirebaseApp.configure()
firebaseApp = FirebaseApp.app()
}
func logEvent(_ event: LoggingEvent) {
Analytics.logEvent(event.eventName, parameters: event.eventParams)
}
}
LogLoggingHandler.swift
(仅打印到控制台)
public class LogLoggingHandler: LoggingHandler {
public func logEvent(_ event: LoggingEvent) {
let name = event.eventName
let description = event.eventParams.description
print("LogEvent: \(name) \(description)")
}
}
这不是最好的解决方案,但这是一个想法。在您的第一个文件中,您可以定义这些类型:
struct LoggingSecurity {
fileprivate init() {}
}
class LoggingManager {
private let handlers: [LoggingHandler]
private let security: LoggingSecurity
init(handlers: [LoggingHandler]) {
self.handlers = handlers
self.security = .init()
}
func broadcast(event: LoggingEvent) {
handlers.forEach { handler in
handler.send(
event: event,
securedBy: security
)
}
}
}
由于 LoggingSecurity.init
方法被标记为 fileprivate
唯一可以实例化 LoggingSecurity
的 class 是 LoggingManager
.
然后在您的其他文件中您可以定义这些类型:
struct LoggingEvent {
let data: String
}
protocol LoggingHandler {
func send(event: LoggingEvent, securedBy security: LoggingSecurity)
}
class PrintLoggingHandler: LoggingHandler {
func send(event: LoggingEvent, securedBy security: LoggingSecurity) {
print("LOG: \(event.data)")
}
}
我有一个 class LoggingManager
和一个协议 LoggingHandler
,只有一个方法 send(LoggingEvent)
。
LoggingManager
保留 LoggingHandler
的列表。
我希望 LoggingManager
成为允许从 LoggingHandler 和使用该协议的 classes 调用 send(LoggingEvent)
的 only class应该实现 send(LoggingEvent)
方法。
我尝试将 LoggingHandler
和 LoggingManager
放入同一个文件并将 send(LoggingEvent)
标记为 fileprivate。
但是,它在协议中是不允许的。
有没有办法让它起作用?
LoggingManager.swift
import Foundation
public struct LoggingEvent {
var eventName: String
var eventParams: [String: Any]
public init(_ name: String, _ eventParams: [String: Any]) {
self.eventName = name
self.eventParams = eventParams
}
public init(_ name: String) {
self.eventName = name
eventParams = [String: Any]()
}
mutating public func addParameter(_ eventName: String, _ eventValue: Any) {
self.eventParams[eventName] = eventValue
}
}
public protocol LoggingHandler {
func logEvent(_ event: LoggingEvent) ///<--- Only LoggingManager should call this function, but classes implementing this should override it
}
public class LoggingManager {
private var loggingHandlers: [LoggingHandler]
static let shared = LoggingManager()
private init() {
loggingHandlers = []
}
public func registerLoggingHandler(_ loggingHandler: LoggingHandler) {
loggingHandlers.append(loggingHandler)
}
public func logEvent(_ event: LoggingEvent) {
for handler in loggingHandlers {
handler.logEvent(event)
}
}
}
FirebaseLogger.swift
class FirebaseLogger: LoggingHandler {
var firebaseApp: FirebaseApp?
public init() {
FirebaseApp.configure()
firebaseApp = FirebaseApp.app()
}
func logEvent(_ event: LoggingEvent) {
Analytics.logEvent(event.eventName, parameters: event.eventParams)
}
}
LogLoggingHandler.swift
(仅打印到控制台)
public class LogLoggingHandler: LoggingHandler {
public func logEvent(_ event: LoggingEvent) {
let name = event.eventName
let description = event.eventParams.description
print("LogEvent: \(name) \(description)")
}
}
这不是最好的解决方案,但这是一个想法。在您的第一个文件中,您可以定义这些类型:
struct LoggingSecurity {
fileprivate init() {}
}
class LoggingManager {
private let handlers: [LoggingHandler]
private let security: LoggingSecurity
init(handlers: [LoggingHandler]) {
self.handlers = handlers
self.security = .init()
}
func broadcast(event: LoggingEvent) {
handlers.forEach { handler in
handler.send(
event: event,
securedBy: security
)
}
}
}
由于 LoggingSecurity.init
方法被标记为 fileprivate
唯一可以实例化 LoggingSecurity
的 class 是 LoggingManager
.
然后在您的其他文件中您可以定义这些类型:
struct LoggingEvent {
let data: String
}
protocol LoggingHandler {
func send(event: LoggingEvent, securedBy security: LoggingSecurity)
}
class PrintLoggingHandler: LoggingHandler {
func send(event: LoggingEvent, securedBy security: LoggingSecurity) {
print("LOG: \(event.data)")
}
}