Jacob Carlborg wrote:
Walter Bright wrote:
Setting aside the technical issues for the moment, isn't that exactly
what inheritance is supposed to be good for?
A few times I've had the need for this, I've always been able to solve
the problem but it would have been easier with support for this. But to
be honest I don't remember these problems right now, so perhaps it's not
that important.
I think it has less to do with how often its needed and more to do with
how much more elegant the solution will be.
Just because I want to supply one example of where it's even appropriate
to use a category-pattern to extend a class' function table without
extending the class into a new type, I'll just spit out something I just
wrote in Objective-C.
===== Short Story =====
I needed to search through a String (NSString) specifically to know
whether a character at a specific index is any one of a given set of
characters. Rather than subclass NSString, I decided to make a category:
== NSString.h ==
#import <Cocoa/Cocoa.h>
@interface NSString (ACSExtensions)
- (bool)characterAtIndex:(int)idx
isOneOf:(NSString*)characters;
@end
== NSString.m ==
#import "NSString.h"
@implementation NSString (ACSExtensions)
- (bool)characterAtIndex:(int)idx
isOneOf:(NSString*)characters {
unichar *arr = malloc([characters length]*sizeof(unichar));
[characters getCharacters:arr];
char ch = [self characterAtIndex:idx];
int lp=([characters length]-1)/10,rm=[characters length]%10;
switch(rm){
case 0: do {
if(ch==arr[lp*10+9]) return YES;
case 9: if(ch==arr[lp*10+8]) return YES;
case 8: if(ch==arr[lp*10+7]) return YES;
case 7: if(ch==arr[lp*10+6]) return YES;
case 6: if(ch==arr[lp*10+5]) return YES;
case 5: if(ch==arr[lp*10+4]) return YES;
case 4: if(ch==arr[lp*10+3]) return YES;
case 3: if(ch==arr[lp*10+2]) return YES;
case 2: if(ch==arr[lp*10+1]) return YES;
case 1: if(ch==arr[lp*10 ]) return YES;
} while(0<--lp);
break;
}
return NO;
}
@end
== end of file ==
As you can see, I added important functionality to the class NSString
without going through all the trouble to make a new class and type cast
between NSString and MyDerivedString all over the place. It's more
transparent, and it's far better than a global function, or placing this
kind of code into an unrelated class, or worse yet, a "kitchen-sink" class.
===== Special Extended Explanation =====
Since some of you may be in a hurry, this part is kind of secondary.
The purpose for adding functionality to NSString is because I'm trying
my hand at writing my own programming language (interpreted, but a
language nonetheless). It's very rudimentary in syntax and capability,
and it's only designed to script the effects of cards in a card game
called Arcomage. I later extended some of its capabilities to make it
suitable for AI scripting as well.
Mind you I haven't implemented the language yet. I just wrote a
specification that I'm now focusing on implementing. If you want to
have a laugh or maybe see how badly I've been spoiled by D, you can read
through the specsheet here:
http://www.fsdev.net/~cmiller/pdf/acs_spec.pdf
And I talk a bit on how I plan to implement such a system over here:
http://www.fsdev.net/~cmiller/a/20090126_acsadv.html
Anyways, the specific and immediate purpose for writing such
functionality into NSString was so that I could - as I was parsing
through the source script - quickly and easily check to see if
characters are certain control characters. For instance, when searching
for an integer, the first task is to read to the first numeric
character. Two options: read to the first numeric character, or (more
resistant to malformed code) read through all the whitespace characters
and then if the next character isn't numeric, you have problems. What
whitespace characters are there?
\t
\r
\n
(space)
Unfortunately, they aren't in sequential order in the ASCII table, so
it's not as simple as determining if char c is numeric:
if ( c > '0' && c < '9' ) // c is numeric
Therefore, it's useful for searching quickly, without getting into the
potential mess that could be a regular expression search. Well, I'm
sure for a lot of people it'd be shorter and more concise, but my
relative ineptitude with regular expressions would make it far more
bothersome for me. Am I here to write a language, or to teach myself
regular expressions?
Anyways, I'm really happy with the ensuing discussion about this - this
is the entire reason why I decided to compare the two languages: in
hopes of bringing up potentially useful features and getting people to
think about them.