2012-01-21 10 views
16

Dato questo:Come creare un'istanza di una classe in Objective-C che non eredita da NSObject

Person.h:

@interface Person 
{ 
} 
- (void) sayHello; 
@end 

Person.m:

#import "Person.h" 

@implementation Person 

- (void)sayHello 
{ 
    printf("%s", "Steve"); 
} 

@end 

Come fare istanziare la persona? Ho provato questo:

Person *p = [Person new]; 

che non funziona, e non questo:

Person *p = [Person alloc]; 

[UPDATE]

ho dimenticato di dire, ho già provato che eredita da NSObject, il nuovo e alloc lavori. Sono solo curioso di sapere se possiamo istanziare una classe che non eredita da NSObject?

+8

Cosa c'è che non va con 'Person' che eredita da' NSObject'? – Costique

+0

+1 in quanto questa è una domanda molto interessante, anche se il valore pratico potrebbe essere molto basso. – vikingosegundo

+0

@Costique: Niente, è solo che ci sono molti tutorial che ho trovato sul Web, non ho menzionato che è un requisito (cioè l'ereditare da NSObject). esempio: http://en.wikibooks.org/wiki/Objective-C_Programming/syntax Provato ad ereditare da Object, ma '[Person new]' non funziona anche – Hao

risposta

28

È assolutamente possibile farlo. La tua classe deve semplicemente implementare lo stesso +alloc, come fa lo NSObject. Alla base, ciò significa semplicemente utilizzare malloc() per afferrare un blocco di memoria abbastanza grande da adattarsi alla struttura che definisce un'istanza della classe.

Anche la gestione della memoria conteggio di riferimento sarebbe buona (retain/release); questo è in realtà parte dello NSObjectprotocol. È possibile adottare il protocollo e implementare anche questi metodi.

Per riferimento, si può guardare the Object class, che è una radice di classe objC come NSObject, che Apple fornisce nel suo repository open source per il runtime Objective-C:

@implementation Object 

// Snip... 

+ alloc 
{ 
    return (*_zoneAlloc)((Class)self, 0, malloc_default_zone()); 
} 

// ... 

- init 
{ 
    return self; 
} 

// And so on... 

Detto questo, si dovrebbe pensare a NSObject come parte integrante del runtime ObjC. C'è poco o nessun motivo per implementare la propria root class al di fuori di curiosità, investigazioni o sperimentazione (che però non dovrebbe essere scoraggiata affatto).

+5

+1 questa è assolutamente la risposta corretta. In realtà, la * sola * volta in cui non vorrai ereditare da 'NSObject' è quando stai andando a fare qualcosa * fondamentalmente diverso * in termini di gestione della memoria. –

+0

Una risposta profonda per quanto riguarda l'obiettivo-c che va oltre: "Fai clic sul pulsante lucido in XCode" ... Impressionante! +1 –

+0

Questa risposta vale anche per swift? – user3797599

-6

non è possibile ..

Alloc e nuova ..copy init tutti questi metodi sono definiti in NSObject ..

Non si può anche creare il proprio dato che Apple non lo fa fornire la classe di implementazione NSObject. Quindi è necessario ereditare da NSObject o dalla sua sottoclasse in modo che sia possibile inizializzare la classe

+2

ovviamente è possibile. Anche Apple l'ha fatto. devi "solo" fare la tua personale gestione della memoria in stile C. NSObject non è una parte della lingua Objective-C, come non è Foundation, UIKit, AppKit, ... – vikingosegundo

+1

Non capisco perché non hai cancellato questa risposta quando è così chiaramente sbagliato. Guadagna un badge Peer Pressure! :) –

4

È necessario:

  1. Eredita da NSObject,
  2. Do Classe A "poveri" con i propri mallocs, ecc, o
  3. Usa Objective-C++ e creare una classe C++.

Naturalmente, nessuno degli altri due si adatta alla gestione della memoria di Objective-C e ai relativi protocolli di chiamata, ecc., Sono diversi.

+2

Quasi! Per 2, puoi semplicemente implementare + alloc, -retain, -release, ecc ... in termini di malloc e del tuo conto personale. Implementando il protocollo * NSObject, è possibile partecipare a un bel po 'di cose in modo trasparente. –

+0

-1 non * deve * ereditare da 'NSObject'. Ci sono un sacco di classi che non lo fanno, come 'NSProxy'. –

+1

@DaveDeLong significa che è necessario * * fare 1. * o * 2. * o * 3. –

3

c'è (molto probabile) nessuna buona ragione a non voler ereditare da NSObject, ma ci sono molte buone ragioni per farlo.

sarei curioso di sapere il motivo per cui non si vuole ereditare da NSObject. Immagino che provenga da una mancanza di conoscenza piuttosto che da un bisogno reale.

Ma anche senza sapere che la ragione: Non farlo. È così difficile farlo bene in modo che giochi ancora bene con altre classi Objective-C per essere praticamente impossibile.

In ogni caso, si sta istanziare gli oggetti in un modo che nasconde ciò che è veramente fatto.Mentre in Java, di solito di creare istanze tramite il metodo di costruzione di default new, in Objective-C si crea un'istanza chiamando alloc sulla classe e poi init sull'istanza:

Person *aPerson = [[Person alloc] init]; 

possibile utilizzare solo Person new, ma non lo farei perché nasconde ciò che è realmente fatto da voi)

Si implementa la classe in modo tale da ereditare da NSObject e quindi, se necessario, scrivere il proprio metodo init.

Se si desidera accedere alla console, utilizzare NSLog:

NSLog(@"Hello %@", @"Steven"); 

(@"" è un costruttore speciale per un NSString stringhe in Objective-C non sono array di byte, ma gli oggetti..)

+3

Ovviamente, in Objective-C 'new' è solo una scorciatoia per vanilla' alloc/init'. –

Problemi correlati