2017-07-29 18 views
0

我有以下代码,我定义了一个Loggable协议,我想在我的应用程序中Element类型符合Loggable易于转换为字符串的任何Array扩展阵列友好的自定义日志

//: 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功能来实现更清晰的日志消息。

回答

0

你有正确的总体思路,但在执行中的几个误区:

  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,因为它实现了与标准库非常类似的功能。

+0

有点相关,是否有可能使协议符合其他协议?例如,你让'Node'符合协议,但是说'Node'是一个协议。假设我希望所有'节点'符合'Hashable',那可能吗? –

+0

和Logger.log应该采用通用约束为Loggable而不是Loggable的具体原因是什么?在这两种情况下,参数的行为都不是'Loggable'? –