Подтвердить что ты не робот

Как вызвать метод super.super?

Я хочу вызвать метод суперкласса суперкласса, не нарушая цепочку наследования. Что-то вроде этого:

+(id) alloc 
{
    return [super.super alloc];
}

Есть ли способ достичь этого?

Не путайте с предложением поведения методом superclass, обсуждаемым здесь.


UPD:

Несколько слов о различиях super и superclass.

Допустим, что мы имеем AClass и SuperAClass. Как следует из их имен AClass наследует SuperAClass. Каждый из них имеет реализацию метода -(void) foo;

AClass реализует один из следующие методы класса:

1. суперкласс:

+(id) alloc {
    return [[self superclass] alloc];
}

2. супер:

+(id) alloc {
    return [super alloc];
}

Теперь предположим, что эти 2 строки кода:

AClass *AClassInstance = [AClass alloc];
[AClassInstance foo];

В первом случае (с использованием суперкласса) будет вызываться метод SuperAClass foo. Для второго случая (с использованием супер) будет вызываться метод AClass foo.

4b9b3361

Ответ 1

В вашем конкретном примере +superclass - это на самом деле способ:

+ (id)someClassMethod {
    return [[[self superclass] superclass] someClassMethod];
}

так как это метод класса, поэтому self относится к объекту класса, где +someClassMethod определяется.

С другой стороны, вещи становятся более сложными в методах экземпляра. Одним из решений является получение указателя на реализацию метода в классе supersuper (grandparent). Например:

- (id)someInstanceMethod {
    Class granny = [[self superclass] superclass];
    IMP grannyImp = class_getMethodImplementation(granny, _cmd);
    return grannyImp(self, _cmd);
}

Аналогично примеру метода класса +superclass отправляется дважды, чтобы получить суперсуперкласс. IMP является указателем на метод, и мы получаем IMP для метода, имя которого совпадает с текущим (-someInstaceMethod), но указывая на реализацию в суперсуперклассе, а затем вызывает его. Обратите внимание, что вам нужно настроить его, если есть аргументы метода и возвращаемые значения, отличные от id.

Ответ 2

Благодаря Bavarious, который вдохновил меня на привлечение персонала во время работы.

Вкратце, желаемая гипотетическая линия:

return [super.super alloc];

можно преобразовать в этом "реальном":

return method_getImplementation(class_getClassMethod([[self superclass] superclass], _cmd))([self class], _cmd);

Чтобы сделать его более понятным, его можно развернуть следующим образом:

Method grannyMethod = class_getClassMethod([[self superclass] superclass], _cmd);
IMP grannyImp = method_getImplementation(grannyMethod);
return grannyImp([self class], _cmd);