首页 文章

从AnyObject扩展的协议和仅类协议之间有什么区别?

提问于
浏览
41

这两个宣言

protocol SomeProtocol : AnyObject {
}

和这个宣言

protocol SomeProtocol : class {
}

似乎是为了使只有类可以符合这个协议(即协议的实例是对象的引用),并且没有其他效果 .

它们之间有什么区别吗?一个人应该优先于另一个吗?如果没有,为什么有两种方法可以做同样的事情?

我正在使用最新发布的Xcode 6.3.1 .

6 回答

  • 3

    关于答案https://forums.swift.org/t/class-only-protocols-class-vs-anyobject/11507/4,这个答案已被弃用 . 这些话现在都是一样的 .

    DEPRECATED

    更新:咨询the powers that be后,两个定义应该是等效的, AnyObject 用作替代 class 完成 . 在未来,后者将消除前者,但目前,它们确实存在一些细微差别 .

    区别在于 @objc 声明的语义 . 对于 AnyObject ,期望符合类可能是也可能不是正确的Objective-C对象,但语言无论如何都将它们视为对待(因为有时会丢失静态分派) . 从中可以看出,你可以治疗 AnyObject 等 . 协议约束作为一种询问 @objc 成员函数的方法,如STL中 AnyObject 文档中的示例所示:

    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'
    }
    

    所以 class 似乎是 AnyObject 的一个更保守的版本,当你只关心引用语义而不关心动态成员查找或Objective-C桥接时,应该使用它 .

  • 4

    AnyObject 是所有类隐式符合的协议(source) . 所以我想说没有区别:你可以使用任何一种来要求类约束 .

  • 10

    The Swift Programming Language (Swift 4)中,在 Class-Only Protocols 部分下 . 它只提到了 AnyObject ,但没有提到 class .

    通过将AnyObject协议添加到协议的继承列表,可以将协议采用限制为类类型(而不是结构或枚举) .

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

    出于这个原因,我建议使用 AnyObject 而不是 class 来获取新代码或新项目 . 除此之外,我认为他们之间没有任何明显的区别 .

  • 0

    这是由Swift forums上的官方Swift开发者(Slava_Pestov)回答的 . 以下是摘要:

    • You should use AnyObjectprotocol SomeProtocol: AnyObject ) .

    • AnyObjectclass 是等效的 . 没有区别 .

    • class 最终将被弃用 .

  • 0

    我以前错过了 . @MartinR应该真的回答这个问题,因为他是纠正我并提供正确信息的人 .

    真正的区别在于具有类限定符的协议只能应用于类,而不能应用于结构或枚举 .

    马丁,你为什么不回答,OP可以接受你的回答?

  • 1

    如果您在Xcode 9中为 class 中的 class 打开帮助(按住alt键单击),您将获得 typealias AnyObject .

    因此,无论是将协议约束为 class 还是 AnyObject ,编译的代码(在Swift 4中)都是相同的 .

    也就是说,还有样式和未来选项的问题 - 未来的Swift版本可能希望以某种微妙的方式对待 classAnyObject ,即使现在情况并非如此 .

相关问题