协议功能实现,实际上没有符合协议

时间:2017-05-02 14:37:37

标签: swift protocols standards-compliance

我是初学Swift学习者,我对协议有疑问。我已经按照教程教你链接列表,如下所示:

节点:

class LinkedListNode<Key> {
    let key: Key
    var next: LinkedListNode?
    weak var previous: LinkedListNode?

    init (key: Key) {
        self.key = key
    }
}

链表:

class LinkedList<Element>: CustomStringConvertible {
    typealias Node = LinkedListNode<Element>

    private var head: Node?

    // irrelevant code removed here

    var description: String {
        var output = "["
        var node = head
        while node != nil {
            output += "\(node!.key)"
            node = node!.next
            if node != nil { output += ", " }
        }
        return output + "]"
    }
}

var description: String实现只允许您打印链表中的每个元素。

到目前为止,我了解链表的结构,我的问题实际上并不是关于链表。我不明白的是协议CustomStringConvertible。如果我只有var description: String实施而不符合协议,为什么会出错呢?我的意思是,这个协议只是简单地说&#34;嘿,你需要实现var description: String,因为你符合我,但为什么我们不能实现var description: String而不符合协议?

是不是因为在后台,有一个函数或某种类型接受CustomStringConvertible类型并通过一些代码运行它瞧!文字出现。

3 个答案:

答案 0 :(得分:1)

为什么我们不能在不符合协议的情况下实施var description: String

比较

class Foo {
    var description: String { return "my awesome description" }
}

let foo = Foo()

print("\(foo)") // return "stackoverflow.Foo" (myBundleName.Foo)

class Foo: CustomStringConvertible {
    var description: String { return "my awesome description" }
}

let foo = Foo()

print("\(foo)") // return "my awesome description"

当您使用CustomStringConvertible时,您保证此类具有变量description,然后,您可以调用它,而无需了解其他实现细节。

另一个例子:

(someObject as? CustomStringConvertible).description

我不知道someObject的类型,但是,如果它订阅了CustomStringConvertible,那么我可以调用description

答案 1 :(得分:1)

如果您希望字符串插值使用CustomStringConvertible属性,则必须符合description

你在Swift中使用字符串插值,如下所示:

"Here's my linked list: \(linkedList)"

编译器基本上将其转换为:

String(stringInterpolation:
    String(stringInterpolationSegment: "Here's my linked list: "),
    String(stringInterpolationSegment: linkedList),
    String(stringInterpolationSegment: ""))

String(stringInterpolationSegment:) defined like this的通用版本:

public init<T>(stringInterpolationSegment expr: T) {
  self = String(describing: expr)
}

String(describing: )defined like this

public init<Subject>(describing instance: Subject) {
  self.init()
  _print_unlocked(instance, &self)
}

_print_unlockeddefined like this

internal func _print_unlocked<T, TargetStream : TextOutputStream>(
  _ value: T, _ target: inout TargetStream
) {
  // Optional has no representation suitable for display; therefore,
  // values of optional type should be printed as a debug
  // string. Check for Optional first, before checking protocol
  // conformance below, because an Optional value is convertible to a
  // protocol if its wrapped type conforms to that protocol.
  if _isOptional(type(of: value)) {
    let debugPrintable = value as! CustomDebugStringConvertible
    debugPrintable.debugDescription.write(to: &target)
    return
  }
  if case let streamableObject as TextOutputStreamable = value {
    streamableObject.write(to: &target)
    return
  }

  if case let printableObject as CustomStringConvertible = value {
    printableObject.description.write(to: &target)
    return
  }

  if case let debugPrintableObject as CustomDebugStringConvertible = value {
    debugPrintableObject.debugDescription.write(to: &target)
    return
  }

  let mirror = Mirror(reflecting: value)
  _adHocPrint_unlocked(value, mirror, &target, isDebugPrint: false)
}

请注意,如果对象符合_print_unlocked,则description仅调用对象的CustomStringConvertible方法。

如果您的对象不符合CustomStringConvertible_print_unlocked中使用的其他协议之一,那么_print_unlocked会为您的对象创建Mirror,最终只打印对象的类型(例如MyProject.LinkedList)而不打印任何其他内容。

答案 2 :(得分:-1)

CustomStringConvertible允许您执行print(linkedListInstance),它将在控制台上打印描述设置器返回的内容。

您可以在此处找到有关此协议的更多信息:https://developer.apple.com/reference/swift/customstringconvertible