Note. For educational purposes only (that's good!), Do not use in production code!
You are also there, just one class ...
To find out why you get recursion, consider how a superclass can be found using information available at compile time and at run time.
At run time, the value of self is a reference to the current object, you can use self to search for the class of the object - in your example, self is an object of type ThirdClass .
Now the value of self does not change as you call methods, so in your example, even in FirstClass forwardMethod value of self is a reference to an object of type ThirdClass . Thus, self allows you to find the type of an object, but it does not tell you where you are currently executing the method in its inheritance chain, therefore, by itself, it cannot tell you what the next class is in this chain.
Therefore, consider compilation time. When compiling SecondClass compiler knows that the superclass is FirstClass , so calling super is a method call in FirstClass (except for the caveat below). Thus, the compiler can use self and [FirstClass class] to determine the runtime object for which to call the method and the compile time class from which to start searching for the method (since the search for any method is a search starting from the class and starting from inheritance chain until an implementation is found). So, in your code example, you were only one way:
@implementation SecondClass - (void)forwardMethod { NSLog(@"second class"); struct objc_super mySuperClass = { self, [FirstClass class] }; objc_msgSendSuper(&mySuperClass, @selector(forwardMethod)); }
If you use this, the code will work. But...
... this is the warning mentioned above. Objective-C allows you to change the inheritance chain at runtime using the swizzling class, so the compiler cannot rely on the whole compilation-time inheritance chain to develop a superclass. So what can he use? Well, when compiling a source for a particular method, it knows the class to which this method belongs, so it can compile this class of methods into code to find the superclass and use the code that starts the method search in the next class by inheritance execution time. This is what the compiler will do for your code, just in case you used the swizzling class:
@implementation SecondClass - (void)forwardMethod { NSLog(@"second class"); struct objc_super mySuperClass = { self, [SecondClass class] }; objc_msgSendSuper2(&mySuperClass, @selector(forwardMethod)); }
Note that the compiler passes the current compilation time class ( [SecondClass class] ) and calls objc_msgSendSuper2 to search - which will find the first method in the run-time inheritance chain, which is after SecondClass m, whereas `objc_msgSendSuper will start the search in SecondClass yourself.
Good luck, but don't use this in general code (unless you have a very, very, very ... very good reason;))