ClassPosing
last edited April 7, 2005 08:15:57 (68.192.175.117)
| |
|---|---|
| Edit / History / New / Search | Quick Links: Home / Recent Changes / Glossary / Jobs / Forums / Help |
|
ExtendingClasses - Large-scale runtime modifications to a class; use rarely. See also PosingClasses
NSObject's poseAsClass: method lets you take a class of your own and use it to replace an existing class. This is useful for changing behavior of an existing class. For example, let's say you create a subclass of NSWindow (we'll call it MyWindow) that draws its elements (title bar, close/minimize/zoom buttons) differently from the Aqua standard. You can already use IB to specify the class of a window object and make it use your subclass, but what if you want your subclass to be used EVERYWHERE in your application, without modifying all your nibs (perhaps you allow a user preference to specify the look of the windows)? poseAsClass: will let you insert MyWindow into the object hierarchy in place of NSWindow; All NSWindow subclasses will now effectively be subclasses of MyWindow. Interesting, MyWindow's superclass will still be the original NSWindow, even though all external accesses to NSWindow will now access MyWindow instead! Example: A piece of the class hierarchy before calling poseAsClass:
after calling [MyWindow poseAsClass:[NSWindow class]]
The important distinction that is not seen in the "after" diagram is that from now on, the original NSWindow can no longer be referenced by name; It still exists and its code will be used wherever MyWindow refers to "super", but it is "invisible" and all references to NSWindow will actually go to MyWindow. For this method to work best, it's important to do the posing as early as possible when the application starts; Inside of the main() function is a good place. See also PosingClasses. StepWise article on posing (and ClassCategories, and when to use each): [http://www.stepwise.com/Articles/Technical/PosersAndCategories/index.html]
So, it seems like posing as a class only guarantees that new objects of that class with use the poser class, and that existing objects won't be converted. Has anybody else found this to be true? (or false?) has anybody else encountered this behavior?
As stated by the second to last sentence of the opening entry. For this method to work best, it's important to do the posing as early as possible when the application starts; Inside of the main() function is a good place
The diagrams above may be the best way to understand it at first, but they aren't exactly correct. The hierarchy goes from
to
A class can only pose for its super class if it has no instance variables, but there's a standard workaround: a static NSMutableDictionary mapping instances to 'ivar' values. It's the same trick used for ClassCategories, and there's sample code over there.
Hypothetical question: what happens if two classes try to pose as the same class. Would the class hierarchy then look like this? --JediKnil
Pretty much. If you look at the strings the runtime print out, it's actually
Note something weird: post posing,
I did some playing around with poseAsClass: and just wanted to share the code with you. It seems method IMP caching could get you into trouble in some rare cases (see code comments).
--GregorNobis
Why don't you use NSLog? This is Cocoa! --JediKnil Well, for me it's not pure Cocoa, I'm working on a project that mixes C, Objective C and Scheme. I know, I could've still used NSLog - but it doesn't seem to make much of a difference. I just wanted to print out a couple o' words and printf did the job. --GregorNobis
I tried this with XCODE 1.5 (ZeroLink) - and it didn't work (using Developer option). However, I found if I used the "Deployment" option, it worked. So, just be aware you might have the same problem. I was trying to pose as NSTimer, and after I did the poseAsClass I put NSLogs? to look at the classes - that is how I found the problem. David | |
| Edit / History / New / Search | Quick Links: Home / Recent Changes / Glossary / Jobs / Forums / Help |