2017-02-26 17 views
1

私はSwiftやObjective-Cの新機能はありませんが、今度はErrorサブタイプで作業すると、それで私は少し深く掘り下げました。スウィフトの動的/ランタイム・ディスパッチ

NSStringサブクラス(NSObjectに基づいたクラスないについても同様に、はい、たとえば以下の機能)で作業する場合:

import Foundation 

// Class version 
class OddString : NSString { 
    override var description: String { 
     return "No way, José" 
    } 
} 

let odd = OddString() 

func printIt(_ string: NSString) { 
    print(string.description) 
} 

print(odd.description) 
printIt(odd) 

私は私が見に期待するものを参照してください。

No way, José 
No way, José 

しかし、私が(と思っているのはです)、代わりに構造体(Error)を使用した同等のコード:

import Foundation 

// Struct version 
struct TestError : Error { 
    var localizedDescription: String { 
     return "I am a TestError" 
    } 
} 

let explosive = TestError() 

func printIt(_ error : Error) { 
    print(error.localizedDescription) 
} 

print(explosive.localizedDescription) 
printIt(explosive) 

私は、次を参照してください。

I am a TestError 
The operation couldn’t be completed. (SanityChecks.TestError error 1.) 

は、これは私には本当に混乱しています。 コンパイル時に決定するのですかprintItに渡された構造体でどのようなメソッドが呼び出されるのですか。どのタイプに関係なくは実際にはですか?

さらに、クラスと構造体の間のランタイム動作の違いがSwift Programming Guideに記載されています。私はまだこれについて何も見つけていない。

+0

との比較[Swiftでエラータイプのローカライズされた説明を提供する方法](http://stackoverflow.com/questions/39176196/how-to-provide-a-localized-description-with-an-error-スイフトタイプ)。 –

+0

関連項目:http://stackoverflow.com/questions/39007960/override-of-protocol-default-implementation-in-a-subsubclass-doesnt-participate、http://stackoverflow.com/questions/31431753/swift-プロトコル拡張のオーバーライド –

答えて

2

最初の例では、descriptionプロパティをオーバーライドしています。したがって、この実装はOddStringのvtable(クラス)に追加され、静的に型付けされているインスタンスに関係なく、動的にディスパッチできるだけです。

2番目の例では、クラスがないため、vtablesはありません。しかし、は、プロトコルに準拠してです。プロトコルは、プロトコル証人テーブル(this great WWDC talkを参照)を介した動的ディスパッチを可能にしますが、これはプロトコル要件の実装でのみ発生します。

localizedDescriptionは、それは単に(これはSE-0112に記載されて)あなたimport FoundationErrorのプロトコル拡張で定義されています、Errorプロトコルのプロトコルの要件ではありません。したがって、動的にディスパッチすることはできません。代わりに、静的にディスパッチされるため、呼び出される実装は、インスタンスのという静的タイプに依存します。

ここに表示されている動作は、explosiveインスタンスがTestErrorと入力されたときに、localizedDescriptionの実装が呼び出されます。 Errorと入力すると、Errorの実装が呼び出されます(NSErrorへのブリッジで、localizedDescriptionとなります)。

ローカライズされた説明を提供する場合は、代わりにLocalizedErrorにエラータイプを準拠させる必要があります。この場合、プロトコル要件としてerrorDescriptionが定義されているため、動的ディスパッチが可能です。これについての例は、this Q&Aを参照してください。

1

localizedDescriptionは、Errorプロトコルの拡張機能であり、エラータイプのプロパティです。あなたの型がプロパティを実装していることをコンパイラが知っているとき、それはそれを使用します。そうでない場合は、拡張子を使用します。動的ディスパッチはありません。

descriptionメンバをオーバーライドすると、コンパイラは実装の参照をvtableに格納するため、動的にディスパッチされます。

関連する問題