2017-05-02 22 views
0

私は初心者です。スイフト学習者です。プロトコルに関する質問があります。私は以下のとおりであるリンクリストについてお教えチュートリアルを、続いている:実際にプロトコルに準拠していないプロトコル機能の実装

ノード:

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に取り、いくつかのコードを介して実行して出来上がり!テキストが表示されます関数またはいくつかの並べ替えがある。

+0

私はあなたの質問を完全に理解しているかどうかはわかりません。なぜ、タイプがただちに要件のすべてを実装した場合、タイプがプロトコルに暗黙的に準拠していないのか尋ねていますか?ほとんどのプロトコルには特定のセマンティクス要件があるため、これが当てはまらない良い理由があります。例えば、 'Error'プロトコルは* no *の要件を持っていますが、*は*すべての型がエラーであることを意味しません。 – Hamish

+0

[Protocols is Syntax of Bags](https://oleb.net/blog/2016/12/protocols-have-semantics/) – Hamish

答えて

1

descriptionプロパティを文字列補間に使用する場合は、CustomStringConvertibleに準拠する必要があります。

あなたはこのようスウィフトの文字列補間を使用し

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

String(stringInterpolationSegment:)defined like thisのジェネリックバージョンがあります:コンパイラは、基本的にこのにいることになります

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

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

String(describing:)はです0:

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

_print_unlockeddefined like thisです:オブジェクトがCustomStringConvertibleに準拠している場合_print_unlockedにのみ、オブジェクトのdescriptionメソッドを呼び出します

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に使用される他のプロトコルのいずれかに適合しない場合は、_print_unlockedだけで、オブジェクトの種類(例えばMyProject.LinkedList)と他には何を印刷し終わるあなたのオブジェクトのためのMirrorを作成します。

+0

ありがとう、それは意味がある –

-1

CustomStringConvertibleあなたが記述セッターによって返されるものは何でもコンソールに出力しますprint(linkedListInstance)を行うことができます。

このプロトコルの詳細については、をご覧ください。 210

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 

私はそれがCustomStringConvertible加入者ならば、その後、私はdescriptionを呼び出すことができ、SomeObjectのタイプを知っているが、しないでください。

関連する問題