协议功能实现,实际上不符合协议
Protocol function implementation without actually conforming to a protocol
我是初学者 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
实现而不符合协议,为什么会出错?我的意思是,这个协议只是简单地说“嘿,你需要实现 var description: String
因为你符合我的要求,但为什么我们不能在不符合协议的情况下实现 var description: String
?
是不是因为在后台,有一个函数或某种类型通过一些代码接收类型 CustomStringConvertible
和 运行,瞧!文本出现。
CustomStringConvertible
允许您执行 print(linkedListInstance)
将描述 setter.
返回的任何内容打印到控制台
您可以在此处找到有关此协议的更多信息:https://developer.apple.com/reference/swift/customstringconvertible
为什么不遵守协议就不能实现var description: String
?
比较:
class Foo {
var description: String { return "my awesome description" }
}
let foo = Foo()
print("\(foo)") // return "Whosebug.Foo" (myBundleName.Foo)
和
class Foo: CustomStringConvertible {
var description: String { return "my awesome description" }
}
let foo = Foo()
print("\(foo)") // return "my awesome description"
当你使用CustomStringConvertible
时,你保证这个class有变量description
,然后,你可以调用它,而无需知道其他实现细节。
另一个例子:
(someObject as? CustomStringConvertible).description
我不知道 someObject 的类型,但是,如果它订阅了 CustomStringConvertible
,那么,我可以调用 description
。
如果您希望字符串插值使用您的description
,您必须符合CustomStringConvertible
。属性。
您在 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_unlocked
是 defined 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)
}
请注意,如果对象符合 CustomStringConvertible
.
,则 _print_unlocked
仅调用对象的 description
方法
如果您的对象不符合 CustomStringConvertible
或 _print_unlocked
中使用的其他协议之一,则 _print_unlocked
会为您的对象创建一个 Mirror
,这最终只打印对象的类型(例如 MyProject.LinkedList
),仅此而已。
我是初学者 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
实现而不符合协议,为什么会出错?我的意思是,这个协议只是简单地说“嘿,你需要实现 var description: String
因为你符合我的要求,但为什么我们不能在不符合协议的情况下实现 var description: String
?
是不是因为在后台,有一个函数或某种类型通过一些代码接收类型 CustomStringConvertible
和 运行,瞧!文本出现。
CustomStringConvertible
允许您执行 print(linkedListInstance)
将描述 setter.
您可以在此处找到有关此协议的更多信息:https://developer.apple.com/reference/swift/customstringconvertible
为什么不遵守协议就不能实现var description: String
?
比较:
class Foo {
var description: String { return "my awesome description" }
}
let foo = Foo()
print("\(foo)") // return "Whosebug.Foo" (myBundleName.Foo)
和
class Foo: CustomStringConvertible {
var description: String { return "my awesome description" }
}
let foo = Foo()
print("\(foo)") // return "my awesome description"
当你使用CustomStringConvertible
时,你保证这个class有变量description
,然后,你可以调用它,而无需知道其他实现细节。
另一个例子:
(someObject as? CustomStringConvertible).description
我不知道 someObject 的类型,但是,如果它订阅了 CustomStringConvertible
,那么,我可以调用 description
。
如果您希望字符串插值使用您的description
,您必须符合CustomStringConvertible
。属性。
您在 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_unlocked
是 defined 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)
}
请注意,如果对象符合 CustomStringConvertible
.
_print_unlocked
仅调用对象的 description
方法
如果您的对象不符合 CustomStringConvertible
或 _print_unlocked
中使用的其他协议之一,则 _print_unlocked
会为您的对象创建一个 Mirror
,这最终只打印对象的类型(例如 MyProject.LinkedList
),仅此而已。