【问题标题】:Extending Array to be friendly to custom logging扩展 Array 以对自定义日志记录友好
【发布时间】:2017-07-29 21:41:31
【问题描述】:

我有以下代码,我在其中定义了一个 Loggable 协议,并且我希望我的应用程序中的任何 Array 类型符合 Loggable 都可以轻松转换为字符串。

//: Playground - noun: a place where people can play

import UIKit

protocol Loggable {
    var logDescription: String { get }
}

struct Node: CustomStringConvertible {
    let id: Int

    var description: String {
        return "node: \(self.id) \n"
    }
}

let node1 = Node(id: 1)
let node2 = Node(id: 2)

let nodes = [node1, node2]

print(nodes)

extension Array: Loggable where Element: Loggable {

    var logDescription: String {
        var message = ""
        for element in self {
            message += element.logDescription
        }
        return message
    }
}


struct Logger {
    static func log(item: Loggable) {
        print(item.logDescription)
    }
}


Logger.log(item: nodes)

不幸的是,我收到了Extension of type 'Array' with constraints cannot have an inheritance clause。有没有办法完成我想做的事情?

更广泛地说,如果有任何关于使用 Swift 功能来实现更清晰的日志消息的建议或链接,我将不胜感激。

【问题讨论】:

    标签: arrays swift logging protocols


    【解决方案1】:

    您的总体思路是正确的,但在执行过程中出现了一些错误:

    1. 首先,您需要使数组元素Node 符合Loggable 协议。数组本身不需要符合,因为它只是Loggable 对象的容器

      struct Node: Loggable, CustomStringConvertible {
          let id: Int
      
          var description: String {
              return "node: \(self.id) \n"
          }
      
          var logDescription: String {
              return "logDescription"
          }
      }
      
    2. 将您的Logger 的日志函数修改为具有约束条件的通用函数,即参数应符合Loggable 协议

      struct Logger {
      
          static func log<T>(item: T) where T: Loggable {
              print(item.logDescription)
          }
      
          static func log<T>(items: [T]) where T: Loggable {
              for item in items {
                  print(item.logDescription)
              }
          }
      
          // Bonus functional points
      
          // static func log<T>(items: [T]) where T: Loggable {
          //     items.forEach() { print($0.logDescription) }
          // }
      
      }
      
    3. 现在您可以按预期调用日志函数了

      let node1 = Node(id: 1)
      let node2 = Node(id: 2)
      let nodes = [node1, node2]
      
      Logger.log(items: nodes)
      

    您应该查看CustomDebugStringConvertible,因为它实现了与标准库非常相似的功能。

    【讨论】:

    • 有点相关的是,是否有可能使一个协议符合另一个协议?例如,您使 Node 符合协议,但说 Node 是协议。假设我希望所有Node 都符合Hashable,这可能吗?
    • 以及为什么Logger.log 应该采用具有Loggable 约束的泛型而不是Loggable 的具体原因是什么?在这两种情况下,参数都不是Loggable吗?
    猜你喜欢
    • 2018-01-24
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-29
    • 2019-11-15
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多