2013-03-09 22 views
5

to fragment Objective-C runtime programming guide:Zrozumienie Cel C wykonawcze

Gdy tworzony jest obiekt, pamięć alokuje i jego zmienne wystąpienia są inicjalizowane. Pierwszą ze zmiennych obiektu jest wskaźnik do jego struktury klasowej. Wskaźnik ten, zwany isa, daje obiektowi dostęp do jego klasy i, poprzez klasę, do wszystkich klas, z których dziedziczy.

ISA jest zadeklarowana w NSObject tak:

Class isa; 

Z kolei Class jest niczym więcej niż wskaźnik do struktury

typedef struct objc_class *Class; 

A teraz przyjrzyjmy się tej struktury:

struct objc_class { 
Class isa; 

#if !__OBJC2__ 
Class super_class          OBJC2_UNAVAILABLE; 
const char *name           OBJC2_UNAVAILABLE; 
long version            OBJC2_UNAVAILABLE; 
long info            OBJC2_UNAVAILABLE; 
long instance_size          OBJC2_UNAVAILABLE; 
struct objc_ivar_list *ivars        OBJC2_UNAVAILABLE; 
struct objc_method_list **methodLists     OBJC2_UNAVAILABLE; 
struct objc_cache *cache         OBJC2_UNAVAILABLE; 
struct objc_protocol_list *protocols      OBJC2_UNAVAILABLE; 
#endif 

} 

Widzimy, że wskaźnik do super klasy (jak również do wszystkich pozostałych członków struct z wyjątkiem innego isa) jest niedostępny w najnowszej wersji Objective-C.

Moje pytanie brzmi: jak obiekt może uzyskać dostęp do swojej nadklasy, jeśli wskaźnik super_class jest niedostępny? Czy ma dostęp do nadklasy poprzez ten inny wskaźnik isa? Ale jak dokładnie to się dzieje? Jak to działa? Czy ktoś może to wyjaśnić?

+0

Gdzie znalazłeś tę definicję? Ten plik nagłówkowy pokazuje inny: http://www.opensource.apple.com/source/objc4/objc4-208/runtime/objc-class.h – trojanfoe

+0

znalazłem go w objc/runtime.h –

+0

to zależy od wersja runtime Myślę, że –

Odpowiedz

7

tylko sprawdzone plik źródłowy

objc-class.m

Class class_getSuperclass(Class cls) 
{ 
    return _class_getSuperclass(cls); 
} 

runtime-new.mm

#define newcls(cls) ((class_t *)cls) 

Class 
_class_getSuperclass(Class cls) 
{ 
    return (Class)getSuperclass(newcls(cls)); 
} 

static class_t * 
getSuperclass(class_t *cls) 
{ 
    if (!cls) return NULL; 
    return cls->superclass; 
} 

tak Class jest rzeczywiście wskaźnik do class_t

objc-runtime-new.h

typedef struct class_t { 
    struct class_t *isa; 
    struct class_t *superclass; 
    Cache cache; 
    IMP *vtable; 
    uintptr_t data_NEVER_USE; // class_rw_t * plus custom rr/alloc flags 

    class_rw_t *data() const { 
     return (class_rw_t *)(data_NEVER_USE & ~(uintptr_t)3); 
    } 
    void setData(class_rw_t *newData) { 
     uintptr_t flags = (uintptr_t)data_NEVER_USE & (uintptr_t)3; 
     data_NEVER_USE = (uintptr_t)newData | flags; 
    } 

    bool hasCustomRR() const { 
#if CLASS_FAST_FLAGS_VIA_RW_DATA 
     return data_NEVER_USE & (uintptr_t)1; 
#else 
     return data()->flags & RW_HAS_CUSTOM_RR; 
#endif 
    } 
    void setHasCustomRR(bool inherited = false); 

    bool hasCustomAWZ() const { 
#if CLASS_FAST_FLAGS_VIA_RW_DATA 
     return data_NEVER_USE & (uintptr_t)2; 
#else 
     return data()->flags & RW_HAS_CUSTOM_AWZ; 
#endif 
    } 
    void setHasCustomAWZ(bool inherited = false); 

    bool isRootClass() const { 
     return superclass == NULL; 
    } 
    bool isRootMetaclass() const { 
     return isa == this; 
    } 
} class_t; 

i jest to struktura, która posiada wszystkiemu

tak, to są wewnętrzne szczegóły implementacji i nie powinny być traktowane na. więc nie pisz kodu, który na nich polega, ponieważ mogą one zostać zerwane podczas następnej aktualizacji środowiska wykonawczego

+0

+1 Dokładnie o poście to samo! – trojanfoe

+0

hej, ale dlaczego po kliknięciu skoku do definicji na klasę dostaję tutaj typedef struct objc_class * Class ;? –

+1

@AndreyChernukha Mogę sobie wyobrazić, że jest tam, aby dać kompilatorowi coś, na co można ukryć rzeczywiste szczegóły implementacji. – trojanfoe

1

Nie polegaj na żadnych elementach wewnętrznych klasy struct. - nie polegaj też na innych zmiennych instancji pals! spojrzeć na właściwości

wszystko można bezpiecznie zrobić ze środowiskiem wykonawczym jest runtime.h

uzyskania nadklasę egcall class_getSuperclass

+0

@downvoter: jak zawsze - dlaczego? rada brzmi: –

+0

+1 w tej odpowiedzi, aby uzyskać rozsądną radę. –