Hi Todd
This is an interesting question. I'm at work in California at the moment (on a Windows machine). I'll reply in more detail this evening. The basic answer however is that all objects are derived from a common base class (NSObject). You can call any method on any object because the run-time system looks up the method before dispatching to theobject.
Remember that Obj/C is C (and Obj/C++ is C++), so you can use a cast to keep the compiler quiet (however you can never fool the run-time system).
NSString* myString = (NSString*) [[NSObject alloc]init] ; When you call [myString capitalizedString] will fail because the run time system will ask myString if he has a method called 'capitalizedString' and he'll throw when he does not.
If you do:NSObject* notAString = [[NSObject alloc]init] ;
[notAString capitalizedString] ;
The compiler will complain (warn) that he isn't sure that notAString has a method called capitalizedString.
If you want to defer the allocation of objects totally until runtime, something like this:
NSString* today = @'Monday' ; // something you know at run time
NSObject myObject;
// the following syntax is wrong !!!!
myObject = [[today alloc]init] ; // create an object at run-time
I know I don't have the correct syntax for this - however I'm confident that this is possible.
I hope this sets you off in the right direction. Please let me know if I'm not answering the question that is in your mind!