类方法的协议

Dan*_*iel 9 swift

我想在协议中声明一个class func,我打算从A,B和C类符合这个协议.

B和C继承自A.

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

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

protocol MyManagedObjectCoolStuff {

    static func entityName() -> String
}
Run Code Online (Sandbox Code Playgroud)

然后我在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"
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的问题很明显,Xcode证实:"类方法会覆盖'最终'类方法".

在此输入图像描述

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

谢谢!

Mar*_*n R 18

定义中,static是别名class final,因此它标记了一个无法在子类中重写的类型方法(或属性).

由于您覆盖子类中的方法,您所要做的就是将方法定义classstatic:而不是:

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"
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,可以使用以下事实:对于Core Data实体,类名通常被定义为<ModuleName>.<EntityName> 实体名称是类名的最后一个组件.

因此,您可以定义entityName()NSManagedObject(所有Core Data对象类的超类)的扩展方法,如在NSManagedObject Swift扩展如何创建托管对象子类的实例?:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

并在必要时覆盖它:

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
Run Code Online (Sandbox Code Playgroud)