Lezione in classe Obiettivo-C

4

Ho le seguenti classi:

   Teacher
   Student
   Class (like a school class)

Si estendono tutti da KObject che ha il seguente codice:

- initWithKey
- send
- processKey

Insegnante, Classe studente utilizzano tutte le funzioni processKey e initWithKey dalla classe genitore KObject. Implementano la propria versione di invio. Il problema che ho è che KObject non dovrebbe essere istanziato mai. È più simile a una classe astratta, ma non esiste un concetto di classe astratto nell'obiettivo-c. È utile solo per consentire alle sottoclassi di accedere a una proprietà e a due funzioni.

Che cosa posso fare in modo che KObject non possa essere istanziato ma consentire comunque alle sottoclassi di accedere alle funzioni e alle proprietà di KObject?

    
posta Pota Onasys 20.10.2013 - 02:40
fonte

4 risposte

2

L'uso di un protocollo è probabilmente il modo più pulito per ottenere il comportamento desiderato. Il commento di Bryan Chen mi ha ricordato uno schema che ho visto mentre esaminavo un codice di analisi legacy. È stata creata una classe astratta che generava eccezioni se chiamate direttamente:

- (void)startAnalyticsSession
{
    [NSException raise:NSInternalInconsistencyException
                format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
}

- (void)stopAnalyticsSession
{
    [NSException raise:NSInternalInconsistencyException
                format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
}

Questo è un esempio approssimativo del modello di adattatore . Nel tuo caso, potresti creare una classe astratta con questi metodi stubati che ereditano tutte le altre classi.

    
risposta data 08.08.2016 - 17:39
fonte
0

KObject potrebbe avere un unico metodo init init: secret In questo modo, solo i chiamanti con il segreto condiviso sarebbero istanziati. Uno svantaggio, tuttavia, è che le sottoclassi dovrebbero conoscere questo codice per passare.

    
risposta data 12.12.2015 - 09:53
fonte
0

Il concetto astratto non esiste in Objective-C, ma cosa può aiutarti Protocols .

Un'altra soluzione è impostare l'implementazione predefinita per generare un'eccezione. Ma c'è un problema con questa soluzione, puoi solo vedere se qualcosa è sbagliato durante il runtime, ma non otterrai errori durante la compilazione, ad esempio in Java o in C #.

Tuttavia, prima di sviluppare ulteriormente, penso che ci sia un problema più grande con la tua applicazione, il design stesso. La tua eredità potrebbe essere infranta.

A meno che gli unici metodi utilizzati dalle classi Teacher , Student e Class non siano i metodi initWithKey , send e processKey , si interrompono intrinsecamente i LSP , e probabilmente dovrebbe andare con la composizione.

    
risposta data 12.12.2015 - 11:38
fonte
0

Puoi usare un protocollo, in questo modo:

@protocol kObject
- (instancetype) initWithKey: (NSString *) key; // I'm assuming the key is a string.
- (void) send;
- (void) processKey;
@end 

Tuttavia, non è raro in Objective-C che gli inizializzatori vengano dichiarati in un protocollo e per applicare l'LSP è necessario digitare qualsiasi metodo o funzione che ha utilizzato una di queste classi come id<kObject> , che è atipico dato il use case.

Generalmente, in Objective-C non c'è nulla che possa impedire l'implementazione o il richiamo di una classe base. Quello che ho fatto in passato è lasciato commenti nell'intestazione, e l'implementazione predefinita ha generato un'eccezione. Non riceverai errori in fase di compilazione, ma il codice si fermerà e potrai applicare i vincoli del tuo design in questo modo.

Penso al motto di Python, "Siamo tutti adulti consenzienti" ogni volta che si tratta di classi astratte in Objective-C - è sul programmatore di far rispettare questo dato la natura altamente dinamica e (praticamente) interamente pubblica di Objective-C . Confido che se dico che non dovrebbe essere fatto, sarà rispettato. Le eccezioni fanno rispettare questo, anche se un po 'pesante. In alternativa, puoi anche far tornare immediatamente i metodi - rendendo la classe inutile.

Per inciso, potresti avere la fortuna di dichiarare la proprietà come una variabile di istanza protected , nel caso non avessi bisogno di altre classi, metodi o funzioni per accedere direttamente alla proprietà kObject .

    
risposta data 11.01.2016 - 13:35
fonte

Leggi altre domande sui tag