Swift扩展名:用方法重载扩充现有类

7gs2gvoe  于 2023-09-30  发布在  Swift
关注(0)|答案(2)|浏览(98)

考虑来自OSLog框架的Logger类:Logger
由于OSLog API不允许查询诸如文件名、调用日志命令的行和函数等信息,因此我想将这些值“嵌入”到日志条目本身中。
这可以通过向Logger添加一个新方法来轻松实现:

extension Logger {
func d_debug(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) {
    let converted = (file as NSString).lastPathComponent + ":" + String(line) + ":" + function + ": " + "\(message())"
    debug("\(converted)")
}

}
这种方法的问题是,我必须使用d_debug方法,而不是默认使用的标准debug方法。因此,这个修改过的方法将把实现细节“泄漏”到扩展之外。
我正在寻找的是一个选项来利用方法重载并使用不同的类型,即。一个String作为输入参数,这样我的方法将是首选的,而不是Logger的原始日志方法。
例如,原始签名看起来像这样:

///
    /// - Warning: Do not explicity create OSLogMessage. Instead pass a string interpolation.
    ///
    /// - Parameter message: A string interpolation.
    public func debug(_ message: OSLogMessage)

但是,我希望有一个这样的方法:

func debug(_ message: @autoclosure () -> String, _ file: String = #file, _ function: String = #function, line: Int = #line) {

并且保持该方法甚至完全隐藏于调用站点之外的概念(如果可能的话)。
理想情况下,如果我删除了扩展,代码应该仍然可以编译。
是否有实现此行为的选项?或者类似的东西会涉及到运行时的动态修补?

new9mtju

new9mtju1#

如果我理解正确的话,您可以将方法命名为debug,并使用log(level:_:)方法来避免无限递归。

log(level: .debug, "\(custom)")

Swift会将debug(...)调用解析为你自己的方法,而不是内置的as long as you are in the same module as the extension方法。
还可以考虑使用OSLogMessage提供的自定义字符串插值。

func debug(_ message: @autoclosure () -> String, _ file: String = #file, _ function: String = #function, line: Int = #line) {
    log(level: .debug, "\((file as NSString).lastPathComponent):\(line):\(function):\(message())")
}

无论哪种方式,调用者都不能使用OSLogMessage提供的自定义字符串插值,例如自定义格式、对齐和隐私。我不认为有办法实现这一点。

fcg9iug3

fcg9iug32#

如果两个函数具有不同的参数,即使它们具有相同的名称,它们也是两个不同的函数。也就是说,您仍然可以使用扩展来执行此操作

extension Logger { 

internal func debug(_ message: @autoclosure () -> String, _ file: String = #file, _ function: String = #function, line: Int = #line) {
    let converted = (file as NSString).lastPathComponent + ":" + String(line) + ":" + function + ": " + "\(message())"
    debug("\(converted)") 
}

==编辑=
我没有意识到所有额外的参数都有默认值。在这种情况下,您仍然可以像下面这样区分函数调用

extension Logger { 

internal func debug(_ message: @autoclosure () -> String, _ file: String = #file, _ function: String = #function, line: Int = #line) {
    let converted = (file as NSString).lastPathComponent + ":" + String(line) + ":" + function + ": " + "\(message())"
    self.debug(_:)("\(converted)") 
}

但我不确定拥有ambuiguity over function signatures是否是一个好主意。

相关问题