Polymorphism in Objective C
I'm trying to write one function that'll create a dictionary of a given class based on a file I'm loading. I'm doing it because at the moment, a near identical function exists in about 5 different unrelated classes and it seems like a bad way to write the code.
Instead, I'm trying to write a polymorphic function (if that's the right term) that looks something like this:
Obviously, there's one line in there (at least) that makes me look like a moron. However, I've never passed a class-type to a function before, and it's all a bit strange to me.
Any suggestions?
Instead, I'm trying to write a polymorphic function (if that's the right term) that looks something like this:
Code:
- (void) setupDataDictionary: (NSMutableDictionary *) dict WithFilename: (NSString *) file OfClass: (Class) class
{
CParser *parser = [[CParser alloc] initWithFilename: file];
if(parser != nil)
{
NSString *line;
while((line = [parser getCurrentLine]) != nil)
{
// Not sure how I write the line below!
class *data = [[class alloc] initWithDataParser: parser];
if(data != nil)
{
[dict setValue: data forKey: data.name];
}
[parser nextLine];
[data release];
}
[parser release];
}
}Obviously, there's one line in there (at least) that makes me look like a moron. However, I've never passed a class-type to a function before, and it's all a bit strange to me.
Any suggestions?
My Obj-C is not as strong as my Ruby, but I think that class objects can be used in the same way you would normally use an actual class name. They have the same methods, but the compiler can't check that the methods exist. Basically the class type is to classes what id is to objects.
So I think you would do this:
The runtime does all method calls as dynamic anyway, so you are just taking type information away from the compiler is all.
So I think you would do this:
Code:
id data = [[class alloc] initWithDataParser: parser];The runtime does all method calls as dynamic anyway, so you are just taking type information away from the compiler is all.
Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Skorche is right.
Have you looked at NSCoder?
It is great for serialization.
You can also directly access type encodings:
http://developer.apple.com/documentation...dings.html
It is great for serialization.
You can also directly access type encodings:
http://developer.apple.com/documentation...dings.html
FreakSoftware Wrote:Skorche is right.
Thanks folks - that seems to fix it.
For those who are interested (and to ensure I put something back into the community rather than just take all the time), here's my code. I love it. It's elegant, and does exactly what you'd expect it to:
Code:
// The main big parser thing
- (NSMutableDictionary *) dataDictionaryFromFilename: (NSString *) file OfClass: (Class) class
{
NSMutableDictionary *dict = [[[NSMutableDictionary alloc] init] autorelease];
[self setupWithFilename: file];
NSString *line;
while((line = [self getCurrentLine]) != nil)
{
id data;
data = [class alloc];
SEL init_function = NSSelectorFromString(@"initWithDataParser:");
if([data respondsToSelector: init_function])
[data performSelector: init_function withObject: self];
if(data != nil)
{
[dict setValue: data forKey: [data name]];
}
[self nextLine];
}
return dict;
}
Not sure what you were going for here exactly, but if the object doesn't respond to the selector, you are calling "name" on an uninitialized object.
Code:
data = [class alloc];
SEL init_function = NSSelectorFromString(@"initWithDataParser:");
if([data respondsToSelector: init_function])
[data performSelector: init_function withObject: self];
// data might be non-nil, but uninitialized here
if(data != nil)
{
[dict setValue: data forKey: [data name]];
}Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Well spotted. Thanks! You've saved me future headaches. Guess who doesn't do unit testing...
...or read his own code, apparently.
...or read his own code, apparently.
Madrayken Wrote:Code:
// The main big parser thing
- (NSMutableDictionary *) dataDictionaryFromFilename: (NSString *) file OfClass: (Class) class
Don't capitalize the first letter of each part of the selector. In other words OfClass should be ofClass. Follow the convention.
Code now looks like this:
What I really wanted was for that central block to be:
However, I don't see a way to perform the selector check on a class. The compiler is happy, but the respondsToSelector: check fails every time.
Code:
- (NSMutableDictionary *) dataDictionaryFromFilename: (NSString *) file ofClass: (Class) class
{
NSMutableDictionary *dict = [[[NSMutableDictionary alloc] init] autorelease];
[self setupWithFilename: file];
NSString *line;
while((line = [self getCurrentLine]) != nil)
{
id data;
data = [class alloc];
SEL init_function = NSSelectorFromString(@"initWithDataParser:");
if([data respondsToSelector: init_function])
{
data = [data performSelector: init_function withObject: self];
if(data != nil)
{
[dict setValue: data forKey: [data name]];
}
}
[self nextLine];
}
return dict;
}What I really wanted was for that central block to be:
Code:
id data;
SEL init_function = NSSelectorFromString(@"initWithDataParser:");
if([class respondsToSelector: init_function])
{
data = [[class alloc] performSelector: init_function withObject: self];
if(data != nil)
{
[dict setValue: data forKey: [data name]];
}
}However, I don't see a way to perform the selector check on a class. The compiler is happy, but the respondsToSelector: check fails every time.
Furthermore, regarding lower-casing parts of method names, if I presume that means I should have functions of the form:
setVertexCoordX: y: z:
rather than:
setVertexCoordX: Y: Z:
This is where I stumbled last time - the former looks counter-intuitive, and indeed, counter camel-script. I presume that's just me, though?
setVertexCoordX: y: z:
rather than:
setVertexCoordX: Y: Z:
This is where I stumbled last time - the former looks counter-intuitive, and indeed, counter camel-script. I presume that's just me, though?
Madrayken Wrote:Furthermore, regarding lower-casing parts of method names, if I presume that means I should have functions of the form:
setVertexCoordX: y: z:
rather than:
setVertexCoordX: Y: Z:
This is where I stumbled last time - the former looks counter-intuitive, and indeed, counter camel-script. I presume that's just me, though?
If it makes sense to break with convention and capitalize, then do it. In your excellent example, I'd take the liberty of doing setVertexCoordX: Y: Z:
Otherwise, yes, as FreakSoftware mentioned, it's the convention to start them off with lower case.
AnotherJake Wrote:If it makes sense to break with convention and capitalize, then do it. In your excellent example, I'd take the liberty of doing setVertexCoordX: Y: Z:
Otherwise, yes, as FreakSoftware mentioned, it's the convention to start them off with lower case.
Thanks, folks. I'm new to the whole objective-C thing, and my hacky nature occasionally reveals itself.

