Re: Dynamic Languages [was: Re: why Obj-C]
Re: Dynamic Languages [was: Re: why Obj-C]
- Subject: Re: Dynamic Languages [was: Re: why Obj-C]
- From: Michael Gersten <email@hidden>
- Date: Wed, 22 May 2002 17:48:40 -0700
>
You got a number of theoretical answers to your original question "why
>
Obj-C", I would like to complement with practical exercises: try to do
>
them in any language you like. I can tell you the solution in Obj-C is, in
>
each case, only one or two lines of code.
>
>
Exercise 1. You are using a standard OOP library, say with a "string"
>
class. However, you need in some different places of your code a method to
>
strip any combination of spaces/tabs/newlines at the end, but the
>
corresponding class does not have this method. What do you do?
>
HINT: in Objective-C, you can add a new method to ANY existing class.
But not to a protocol.
If you are using DO, you are probably using a protocol checker.
You cannot update the protocol that the checker uses
(Please, tell me that I'm wrong -- I'd love to be wrong here)
Also, you might be told that a return from a method is defined by a protocol. How can you now say "I'm expanding this protocol to include this new function defined in terms of other things in the protocol"?
>
Exercise 2: In the same library, there is a method for removing spaces at
>
the beginning, but unfortunately this method has a bug. What do you do?
>
HINT: in Objective-C, you can override any method of any existing class.
Not entirely true.
Categories can only override a base class method.
You cannot override a method in a category with a category.
PoseAs will allow you to _subclass_ these, but that's not the same as override. This is the "Super's super" problem -- how do you skip a buggy intermediate implementation and use the grandparent version?
PoseAs will NOT allow you to replace all classes. You cannot replace NSObject, NSArray, I think NSDictionary, and maybe a few other. These are all instantiated during the call to poseAsClass:, and the (4.5 Yellow box/NT version) would not permit replacing a class once that class had gotten an +initialize call. Back in the old NX- (not NS-) days, there was a documented C runtime call that you could use to poseAs on any class, even Object and NXObject, provided that you called them early (say, in your main(), or in some hidden _environment_specific_startup() that ran before main.
PoseAs is probably not sufficient for class clusters, unless you want to do a _LOT_ of work. Say, have alloc return a "MyOverrideClassWithAClusterIVar" and see exercise 3 and 5.
Neither poseAsClass: nor categories will work if all you know is "The object returned by this call obeys this protocol, but the actual class is a hidden, private class that you cannot access directly."
(Or: Can you, in fact, categorize a hidden base class? I never tried.)
Hmm, come to think of it, this is the basic problem of protocols: You cannot have an unclassed method. You cannot have a protocol of a couple of base routines that are class specific, and a bunch of other routines that are not class specific and use those base methods. You know, like 'count' and 'objectAtIndex:'. You have to have a class cluster for this. And there's no reason that the root of the cluster even needs to be public if something else will dispense these objects.
>
Exercise 3: You designed a class whose object have different contents or
>
different sizes, depending on which "constructor" is called (or on the
>
value of the constructors). What do you do?
>
HINT: In Objective-C, the "init" method is just a method. It can assign to
>
self and return a different object if needed.
And, the "alloc" method is just a method. You can, for example, a class whose alloc returns a different class. For example, +[MyClassCluster alloc] might return an object of MyUninitializedPlaceholder, so you could easily tell an initialized object from an uninitialized object.
Note: You probably do NOT want to assign to self, even in an init.
You probably just want to release self, and return a new object.
Now, my favorite:
Exercise 5: You want to have an object that behaves like another object, but doesn't relate to it. [As an example, you might an object that represents a file, or a printer, that you can draw graphics into]. You want to intercept any other-object related call that is sent to you, and forward it on to an instance variable of yours (that is that object).
Keep in mind: a static list of methods will not work. The drawing library may be added to at any upgrade, and (per Exercise 1), any class can be expanded.
HINT: In objective C, you can trap any message sent to you that you don't implement, and check and see if it's implemented by this instance variable, or that instance variable, or ...
[Note that you'll have to worry about meta messages, such as -class or -isKindOfClass: or respondsTo:]
Exercise 6: You want to implement a FuBi like system. According to the designer of Dungeon Siege, FuBi is the only way that Dungeon Siege was doable.
Functionally, FuBi allows a scriptable language to call a C++ function; any function in the source code can be marked (via window's DLL export) for exporting, and by using a debugging function, the mangled C++ function name can be converted to text to determine the arguments and types. FuBi also allows a network of machines with the same program to send message calls over a network pipe, by making the first line of the function a network redirector call (which tests for the 'same machine' case).
HINT 1: Objective C gives you DO for free.
HINT 2: Objective C protocols include the type information, and are examinable at runtime. (Not free; requires explicitly listing which functions are exported in a second list. Can be automated.)
HINT 3: Objective C message signatures include argument type info for free. [This is used when a DO call is made without a protocol checker]. (Includes too much information; requires filtering to limit to only the "export these" calls.)
Note that this is a significant real-world example; although the basic FuBi was only about a week, FuBi now represents over a year's work by Gas Powered Games, and is essentially the ObjC reflection system, DO, and a compiler/executable-format marking system. Also note that FuBi exports C++ _FUNCTIONS_ -- no access to the c++ vtable for messaging. Each C++ method to export needs an exported C++ function to call it.
[Fubi link:
http://www.drizzle.com/~scottb/gdc/fubi-paper.htm ]
--
I am a Mac 10-Cocoa/WOF/EOF developer, and I'm available for hire. Please contact me at michael-job @ stb.nccom.com if interested.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.