web-dev-qa-db-ja.com

AnyObjectから拡張されたプロトコルとクラスのみのプロトコルの違いは何ですか?

この宣言の両方

protocol SomeProtocol : AnyObject {
}

そしてこの宣言

protocol SomeProtocol : class {
}

クラスだけがこのプロトコルに準拠できるように(つまり、プロトコルのインスタンスがオブジェクトへの参照であるように)構成されているように見え、他の影響はありません。

それらの間に違いはありますか?一方が他方よりも優先されるべきですか?そうでない場合、なぜ同じことをする2つの方法があるのですか?

最新のXcode 6.3.1を使用しています。

57
user102008

これは、公式のSwift dev(Slava_Pestov) Swift forums によって回答されました。概要は次のとおりです:

  • AnyObjectprotocol SomeProtocol: AnyObject)。

  • AnyObjectclassは同等です。違いはありません。

  • classは、最終的には廃止される予定です。
13
kgaidis

回答 https://forums.Swift.org/t/class-only-protocols-class-vs-anyobject/11507/4 については、この回答は非推奨です。これらの言葉は今も同じです。

[〜#〜]非推奨[〜#〜]

更新: べき乗 を参照した後、2つの定義はと同等と見なされAnyObjectが代用として使用され、classは終了しています。将来、後者は前者を取り除くでしょうが、今のところ、いくつかの小さな違いがあります。

違いは、@objc宣言のセマンティクスにあります。 AnyObjectでは、準拠するクラスが適切なObjective-Cオブジェクトである場合とそうでない場合がありますが、言語はそれらをそのように扱います(静的ディスパッチを失う場合があるため)。これからのポイントは、AnyObjectなどを処理できることです。 STLのAnyObjectのドキュメントの例に示すように、@objcメンバー関数を要求する方法としてのプロトコル制約:

import Foundation
class C {
     @objc func getCValue() -> Int { return 42 }
}

// If x has a method @objc getValue()->Int, call it and
// return the result.  Otherwise, return nil.
func getCValue1(x: AnyObject) -> Int? {
    if let f: ()->Int = x.getCValue { // <===
        return f()
    }
    return nil
}
 // A more idiomatic implementation using "optional chaining"
func getCValue2(x: AnyObject) -> Int? {
    return x.getCValue?() // <===
}
 // An implementation that assumes the required method is present
func getCValue3(x: AnyObject) -> Int { // <===
    return x.getCValue() // x.getCValue is implicitly unwrapped. // <===
}

これをclass- derivingプロトコルに変更すると、同じ例がすぐに失敗します。

import Foundation

protocol SomeClass : class {}

class C : SomeClass {
    @objc func getCValue() -> Int { return 42 }
}

// If x has a method @objc getValue()->Int, call it and
// return the result.  Otherwise, return nil.
func getCValue1(x: SomeClass) -> Int? {
    if let f: ()->Int = x.getCValue { // <=== SomeClass has no member 'getCValue'
        return f()
    }
    return nil
}

// A more idiomatic implementation using "optional chaining"
func getCValue2(x: SomeClass) -> Int? {
    return x.getCValue?() // <=== SomeClass has no member 'getCValue'
}

// An implementation that assumes the required method is present
func getCValue3(x: SomeClass) -> Int { // <===
    return x.getCValue() // <=== SomeClass has no member 'getCValue'
}

したがって、classAnyObjectのより保守的なバージョンであり、動的なメンバーのルックアップやObjective-Cブリッジングではなく、参照セマンティクスのみに関心がある場合に使用する必要があるようです。

10
CodaFi

プロトコル用のSwiftプログラミング言語ガイドClass-Only Protocolsセクションの下。 AnyObjectについてのみ言及し、classについては言及していません。

AnyObjectプロトコルをプロトコルの継承リストに追加することで、プロトコルの採用をクラスタイプ(構造体や列挙型ではない)に制限できます。

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

そのため、新しいコードや新しいプロジェクトにはAnyObjectよりもclassを使用することをお勧めします。それ以外は、はっきりとした違いはありません。

5
Yuchen Zhong

AnyObjectは、すべてのクラスが暗黙的に準拠するプロトコルです( source )。だから私は違いはないと言います:あなたはクラス制約を要求するためにどちらを使うこともできます。

4
József Vesza

Xcode 9でprotocol P: class {}などの行でclassのヘルプを開く(alt-クリック)と、typealias AnyObjectが表示されます。

したがって、(Swift 4で)コンパイルされたコードは、プロトコルをclassまたはAnyObjectに制限するかどうかに関係なく同じになります。

そうは言っても、styleおよびfuture optionsの問題もあります—将来のSwiftバージョンでは、classAnyObjectを別の方法で処理する必要があるかもしれません微妙な方法で、たとえ今はそうではないとしても。

0
idrougge

前に間違えた。 @MartinRは私に修正して正しい情報を提供してくれたので、これに本当に答えるべきです。

realの違いは、クラス修飾子を持つプロトコルはクラスにのみ適用でき、構造体や列挙型には適用できないことです。

マーティン、答えてみてください、そしてOPはあなたの答えを受け入れることができますか?

0
Duncan C