2013-03-09 3 views
5

Это отрывок из Objective-C runtime programming guide:Понимание Objective-C во время выполнения

Когда создается новый объект, память для него выделяется, и его переменные экземпляра инициализируются. Первым среди переменных объекта является указатель на его структуру классов. Этот указатель, называемый isa, предоставляет объекту доступ к его классу и через класс ко всем классам, на которые он наследует.

иша объявлен в NSObject так:

Class isa; 

В свою очередь Class ничего больше, чем указатель на структуру

typedef struct objc_class *Class; 

А теперь давайте посмотрим на эту структуру:

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 

} 

Мы видим, что указатель на суперкласс (как и все остальные члены структуры, кроме другого) isas недоступен в последней версии Objective-C.

Итак, мой вопрос в том, как объект может получить доступ к его суперклассу, если указатель super_class не доступен? Получает ли доступ к суперклассу через этот другой указатель? Но как это происходит? Как это работает? Может ли кто-нибудь объяснить это?

+0

Где вы нашли это определение? Этот заголовочный файл показывает другое: http://www.opensource.apple.com/source/objc4/objc4-208/runtime/objc-class.h – trojanfoe

+0

Я нашел его в objc/runtime.h –

+0

это зависит от версия исполнения я думаю –

ответ

7

только что проверил исходный файл

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; 
} 

так Class на самом деле указатель на 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; 

и это структура, которая держит все

в любом случае, это внутренние детали реализации и не должны использоваться на. поэтому не пишите код, который полагается на них, потому что они могут быть повреждены при следующем обновлении во время выполнения.

+0

+1 Как раз о почте то же самое! – trojanfoe

+0

эй, но почему, когда я нажимаю прыжок в определение по классу, я получаю здесь typedef struct objc_class * Class ;? –

+1

@ AndreyChernukha Я бы предположил, что это там, чтобы дать компилятору что-то посмотреть, на котором скрываются фактические детали реализации. – trojanfoe

1

dont полагаться на любые внутренние элементы класса struct. - вы также не полагаетесь на другие переменные экземпляра pals! вы посмотрите на свойства

все, что вы можете спокойно делать с выполнения в runtime.h

для получения суперкласса egcall class_getSuperclass

+0

@downvoter: как всегда - почему? совет звучит –

+0

+1 на этом ответе за здравый совет. –