2015-03-05 7 views
7

ho questo codice:metodi della superclasse di tornare tipo sottoclasse in rapida

class Dark: NSObject { 
    class var className: String { 
    return NSStringFromClass(self)!.componentsSeparatedByString(".").last! 
    } 

    var success = 0 

    class func devour<T: Dark>(params: Int) -> T { 
    var s = T() 
    return assign(s, params: params) 
    } 

    class func assign<T: Dark>(item: T, params: Int) -> T{ 
    if item.dynamicType === self { 
     item.success = params 
    } 
    return item 
    } 
} 

class Black: Dark { 
} 

class Violet: Dark { 
} 

Black.className // returns "Black" 
Violet.className // returns "Violet" 

Il problema si verifica quando faccio questo:

var ret = Black.devour(5) 
ret.success //returns 0 which I expect to be 5 

ret.self // returns {Dark success 0} which I expect to be {Black success 0} 

Il problema qui è che quando la sottoclasse utilizza il metodo ereditato divorare, restituisce un oggetto di tipo Dark. Voglio essere in grado di restituire il tipo di sottoclasse e non il tipo di superclasse quando si chiama divorare. Esempio quando lo faccio:

var ret = Black.devour(5) 

La classe di ret dovrebbe essere di classe Black e non di classe Dark.

Spero che qualcuno possa aiutarmi in questo. Sono davvero fuori dalle idee. Grazie! Voglio evitare il concatenamento e lo considero l'ultima spiaggia.

+0

Qual è esattamente il tuo problema? Registro errori per favore –

+0

Vedere http://stackoverflow.com/questions/26296938/returning-a-subclass-from-its-base-class-in-swift –

+0

hi @RobinEllerkmann: Il problema qui è che quando la sottoclasse utilizza il metodo ereditato divorare, restituisce un oggetto di tipo Dark. Voglio essere in grado di restituire il tipo di sottoclasse e non il tipo di superclasse quando si chiama divorare – oregon

risposta

7

Si è scoperto che ero in grado di fare un lavoro in giro; Grazie alla risposta a questa domanda: Cast to typeof(self).

Tutto ciò che devo fare è creare un metodo che restituisca un oggetto di tipo Self.

Per prima cosa, ho creato una classe che crea un'istanza della classe base e la restituisce come un'istanza di AnyObject.

class func createDark() -> AnyObject { 
      var black = Black() 
      return black 
    } 

Quando torno un'istanza Black getta automaticamente in ANYOBJECT dal momento che era il tipo di ritorno specificato dal metodo (Onestamente appena capito questo e questo mi ha salvato).

Poi creato un metodo di supporto che chiama createDark() e assegna proprietà/attributi dell'istanza:

class func prepare<T: Dark>(params: Int) -> T{ 
     var dark = createDark() as T 
     dark.assign(params) 
     return dark 
    } 

Ho usato tipo generico, che è di tipo o Dark sua sottoclasse come un tipo di ritorno.

poi ho fatto questo:

class func devour(params: Int) -> Self { 
     return prepare(params) 
    } 

specificando Self come tipo di ritorno, si getta automaticamente al tipo di auto che può essere di tipo Dark o di ogni classe che eredita esso.

Il mio codice finale è simile al seguente:

class Dark: NSObject { 
    var success = 0 

    func assign(params: Int) { 
     if self.dynamicType === self { // I dont really have to do this anymore 
      self.success = params 
     } 
    } 

    class var className: String { 
     return NSStringFromClass(self)!.componentsSeparatedByString(".").last! 
    } 

    class func createDark() -> AnyObject { 
     var black = Black() 
     return black 
    } 

    class func prepare<T: Dark>(params: Int) -> T { 
     var dark = createDark() as T 
     dark.assign(params) 
     return dark 
    } 

    class func devour(params: Int) -> Self { 
     return prepare(params) 
    } 


} 

per controllare se ha risolto il problema:

var ret = Black.devour(5) 
ret.success //now returns 5 as expected 

ret.self // now returns {Black success 0} as expected 

funziona come previsto!

+2

Qual è il punto se devi scrivere Black() esplicitamente nella tua superclasse?Cosa succede se voglio fare lo stesso con Violet, o qualche futura sottoclasse che non esiste ancora? –