2015-08-21 4 views
9

Quindi stavo pensando a un modello personalizzato nel mio progetto, ma non riesco a farlo funzionare. L'idea principale è di cambiare il typealias in ogni sottoclasse per ottenere l'accesso all'interfaccia specifica della sottoclasse.Swift: typealias di override nella sottoclasse

protocol InstanceInterface: class { 

    typealias Interface 

    var interface: Interface { get } 
} 

// Baseclass 
protocol FirstClassInterface: class { /* nothing here for the example */ } 

class FirstClass: InstanceInterface, FirstClassInterface { 

    typealias Interface = FirstClassInterface 

    var interface: Interface { return self } 
} 

// Subclass 
protocol SecondClassInterface: FirstClassInterface { 

    func foo() 
} 

class SecondClass: FirstClass, SecondClassInterface { 

    typealias Interface = SecondClassInterface // <--- This does nothing :(

    func foo() { print("hello world") } // Swift 2.0 here 
} 

// Lets say I want to call foo trough the interface 
let test = SecondClass() 

test.interface.foo() // 'Interface' does not have a member named 'foo' 

C'è qualcosa che sto facendo male o fraintendo alcuni concetti Swift qui ?! Ho bisogno di sottoclasse qui per non implementare tutto da protocolli di super-classe più e più volte. Il mio piccolo motivo è anche possibile? Apprezzerei qualsiasi aiuto. :)

risposta

6

Sfortunatamente non esiste una buona soluzione per questo problema.

L'idea principale di ignorare il typealias funzionerebbe in questo caso, ma si consideri il seguente:

protocol TakeAndGet { 
    typealias T 
    func take(value: T) 
    func get() -> T 
} 

class FirstClass: TakeAndGet { 
    typealias T = FirstClass 

    var property = 0 

    func take(value: T) { 
     value.property = 4 
    } 

    func get() -> T { 
     return FirstClass() 
    } 
} 

class SecondClass: FirstClass { 

    typealias T = SecondClass 

    var property2 = "hello" 
} 

Se la typealias del SecondClass sovrascrive l'altro metodo take funzionerebbe poiché richiede una sottoclasse che può essere trattati come la superclasse. Ma il metodo get non può convertire implicitamente FirstClass in SecondClass. Pertanto non è possibile sovrascrivere un typealias.

Ora, se si desidera ignorare la funzione get con get() -> SecondClass, non funzionerebbe poiché non ha la stessa firma di quella nella superclasse. Inoltre abbiamo ereditato il metodo get che si traduce in un uso ambiguo:

SecondClass().get() // which type gets returned? SecondClass or FirstClass 

Quindi devi provare un approccio diverso.

+1

Vedo il punto ora. Ma ancora dovrebbe esserci qualche tipo di errore o avvertimento se si sostituiscono le tipealie all'interno della sottoclasse !? Voglio dire che non fa nulla, anche per il tuo esempio rimarrà comunque su FirstClass in SecondClass, o sbaglio ancora? Qual è il punto di prevalere tipealias? – DevAndArtist

+1

@DevAndArtist Il punto è che un 'typealias' non può essere sovrascritto e se si dichiara uno nuovo con lo stesso nome come in' SecondClass' ombreggia l'altro. Ciò significa che 'T' è nell'ambito di' SecondClass' un tipo diverso ma non modifica 'T' di' FirstClass'. – Qbyte

5

Sarebbe qualcosa di simile a questo lavoro per i vostri scopi?

class MyClass<T> { 

} 

class MySubclass1: MyClass<String> { 

} 

class MySubclass2: MyClass<Int> { 

}