类方法的协议

Posted

技术标签:

【中文标题】类方法的协议【英文标题】:Protocol for class method 【发布时间】:2015-06-29 10:34:46 【问题描述】:

我想在一个协议中声明一个class func,我打算从A、B和C类中遵守这个协议。

B 和 C 继承自 A。

基本上我想在 B 和 C 中覆盖这个函数,同时仍然在 A 中提供一个实现。

所以,我必须如下声明我的协议:

protocol MyManagedObjectCoolStuff 

    static func entityName() -> String

然后我在 A 中有这个:

class A: NSManagedObject  

class B: A  

class C: A  

extension A: MyManagedObjectCoolStuff 

  static func entityName() -> String 
        return "Animal"
    


extension B: MyManagedObjectCoolStuff 

   override static func entityName() -> String 
        return "Bat"
    


extension C: MyManagedObjectCoolStuff 

   override static func entityName() -> String 
        return "Cat"
    

这里的问题很清楚,Xcode 确认:“类方法覆盖了‘最终’类方法”。

我该如何解决这个问题?我不能在协议中使用class func...我不知道如何抽象它。

谢谢!

【问题讨论】:

去掉B和C处的override static,一个静态函数不能有两种实现 另外,不要让 B 和 C 从 A 继承。 【参考方案1】:

class 定义中,staticclass final 的别名, 所以它标记了一个不能被覆盖的类型方法(或属性) 在子类中。

由于您想要覆盖子类中的方法, 您所要做的就是将方法定义为class 而不是static

extension A: MyManagedObjectCoolStuff 

    class func entityName() -> String 
        return "Animal"
    


extension B: MyManagedObjectCoolStuff 

    override class func entityName() -> String 
        return "Bat"
    


extension C: MyManagedObjectCoolStuff 

    override class func entityName() -> String 
        return "Cat"
    


另外,可以使用这样一个事实,即对于核心数据实体, 类名通常定义为<ModuleName>.<EntityName> 这样实体名就是类名的最后一个组成部分。

因此您可以将entityName() 定义为 NSManagedObject的扩展方法(所有Core Data的超类 对象类)如How can I create instances of managed object subclasses in a NSManagedObject Swift extension?:

extension NSManagedObject 

    class func entityName() -> String 
        let classString = NSStringFromClass(self)
        // The entity is the last component of dot-separated class name:
        let components = split(classString)  $0 == "." 
        return components.last ?? classString
    

并仅在必要时覆盖它:

class A: NSManagedObject  

class B: A  

class C: A  

extension C 

    override class func entityName() -> String 
        return "Cat"
    


println(A.entityName()) // A
println(B.entityName()) // B
println(C.entityName()) // Cat

【讨论】:

@MatteoPiombo:感谢您的编辑建议,但我的目的是表明可以使用问题中的扩展方法解决问题。直接在class A 中定义class func entityName()(如您现在已删除的答案)可能是合适的,但对我来说似乎与问题无关。这种方法的另一个问题是 NSManagedObject 子类可以从 Xcode 自动生成。 ...再次考虑您的建议导致了“附录”:)

以上是关于类方法的协议的主要内容,如果未能解决你的问题,请参考以下文章

类方法的协议

iOS类目延展和协议

GroovyMOP 元对象协议与元编程 ( Expando 动态类 | 创建动态类 | 为动态类增加字段和方法 )

协议与委托

GroovyMOP 元对象协议与元编程 ( 使用 Groovy 元编程进行函数拦截 | 通过 MetaClass#invokeMethod 方法调用类其它方法 )

GroovyMOP 元对象协议与元编程 ( 方法合成引入 | 类内部获取 HandleMetaClass )