2015-06-29 16 views
9

chcę deklarować w formie protokołu ustaleń class func, zamierzam być zgodne z tym protokołem z klasy A, B i C.Protokół metody klasy

B i C dziedziczą z A.

Zasadniczo I aby zmienić to func w B i C, a jednocześnie zapewniając realizację w A.

Więc musiałem zadeklarować moje protokół następująco:

protocol MyManagedObjectCoolStuff { 

    static func entityName() -> String 
} 

a potem mam t jego w 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" 
    } 
} 

Problemem tutaj, jest jasne i Xcode potwierdza: „metoda klasy zastępuje się«ostateczny»metody klasy”.

enter image description here

Jak można to obejść? Nie mogę użyć class func w protokole ... Nie jestem pewien, jak to streścić.

Dzięki!

+0

usuń "override static" w B i C, nie może być dwóch implementacji funkcji statycznej. – Daniel

+0

Alternatywnie, nie powoduj dziedziczenia B i C z A. – Daniel

Odpowiedz

18

W klasy definicji static jest aliasem dla class final, więc oznacza to metodę typu (lub mienia), które nie mogą być pominięte w podklasach.

Od chcesz przesłonić metodę w podklasach wszystko co musisz zrobić, to określić metodę jako class zamiast 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" 
    } 
} 

Alternatywnie można skorzystać z faktu, że dla jednostki danych podstawowych: nazwa klasy to zwykle zdefiniowana jako <ModuleName>.<EntityName> , więc nazwa encji jest ostatnim składnikiem nazwy klasy .

Tak można zdefiniować entityName() jako metoda wydłużania NSManagedObject (nadklasy wszystkich danych Core klas obiektów), jak w 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 
    } 
} 

i zastąpić go tylko w razie konieczności:

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 
+0

@MatteoPiombo: Dzięki za sugestię edycji, ale moim zamiarem było pokazanie, że problem można rozwiązać za pomocą metod rozszerzenia z pytania. Definiowanie 'class func entityName()' bezpośrednio w 'klasie A' (jak w twojej teraz usuniętej odpowiedzi) * może * być odpowiednie, ale wydaje się niezwiązane z problemem dla mnie. Innym problemem z tym podejściem jest to, że podklasy NSManagedObject mogą być automatycznie generowane z Xcode. –

+0

... i myślenie o Twojej sugestii ponownie doprowadziło do "addendum" :) –