Today, I saw an article titled "objective-c" in the garden.
2.0 with cocoa Foundation --- 5, class type, selector and function pointer ", I have made a wonderful speech and can't help but put it Code Add notes here for future viewing. My personal experience: the "class type variable" in obj-C is more flexible than the object base class in C #. It can be used to generate any type of instance (but it is not nsobject ). If the selector SEL and the function pointer IMP must be related to C #, the two should be combined, similar to reflection + delegation in C #. You can name a string based on a method, call the method directly. Cattle. h
# Import <Foundation/Foundation. h> @ interface cattle: nsobject {int legscount;}-(void) saysomething;-(void) setlegscount :( INT) count; @ end
Cattle. m
# Import "cattle. H "@ implementation cattle-(void) saysomething {nslog (@" Hello, I am a cattle, I have % d legs. ", legscount);}-(void) setlegscount :( INT) Count {legscount = count;} @ end
Subclass "bull" bull. h
# Import <Foundation/Foundation. h> # import "cattle. H "@ interface BULL: cattle {nsstring * skincolor;}-(void) saysomething;-(nsstring *) getskincolor;-(void) setskincolor :( nsstring *) color; @ end
Bull. m
# Import "bull. H "@ implementation bull-(void) saysomething {nslog (@" Hello, I am a % @ bull, I have % d legs. ", [self getskincolor], legscount);}-(nsstring *) getskincolor {return skincolor;}-(void) setskincolor :( nsstring *) color {skincolor = color;} @ end
Proxy class doproxy. H (the key code is here)
# Import <Foundation/Foundation. h> // define several string constants # defineset_skin_color @ "setskincolor:" # definebull_class @ "bull" # definecattle_class @ "Cattle" @ interface doproxy: nsobject {bool notfirstrun; id cattle [3]; // defines two selector sel say; SEL skin; // defines a function pointer (the processing method of the traditional C Language) void (* setskincolor_func) (ID, sel, nsstring *); // defines an imp function pointer (recommended in obj-C) imp say_func; // defines a class bullclass;}-(void) dowithcattleid :( ID) acattle colorparam :( nsstring *) color;-(void) setallivars;-(void) selfuncs;-(void) functionpointers; @ end
Doproxy. m
# Import "doproxy. H "# import" cattle. H "# import" bull. H "@ implementation doproxy // Initialize all variables-(void) setallivars {cattle [0] = [cattle new]; bullclass = nsclassfromstring (bull_class ); // that is, cattle [1] and cattle [2] are bull class instances. Cattle [1] = [bullclass new]; cattle [2] = [bullclass new]; say = @ selector (saysomething); Skin = nsselectorfromstring (set_skin_color);} // initialization ID-(void) dowithcattleid :( ID) acattle colorparam :( nsstring *) Color {// If (notfirstrun = No) {nsstring * myname = nsstringfromselector (_ cmd) during the first run ); // obtain the name nslog (@ "running in the method of % @", myname); notfirstrun = yes; // modify the initial run flag} nsstring * cattleparamclassname = [acattle classname]; // obtain acattle's "Class Name" // If acattle is a bull or cattle class instance if ([cattleparamclassname isw.tostring: bull_class] | [cattleparamclassname isw.tostring: cattle_class]) {[acattle setlegs Count: 4]; // set the four legs of a cow if ([acattle respondstoselector: Skin]) // If acattle corresponds to a class, there is a defined method "setskincolor" {[acattle javasmselector: Skin withobject: Color]; // call the setskincolor method} else {nslog (@ "Hi, I am a % @, have not setskincolor! ", Cattleparamclassname); // otherwise, the corresponding prompt message is output.} [acattle implements mselector: Say]; // The saysomething method is last executed. (both methods are available in the bull and cattle classes, so it will certainly run)} else // If acattle is neither a bull class nor a cattle class instance {nsstring * yourclassname = [acattle classname]; nslog (@ "Hi, you are a % @, but I like cattle or bull! ", Yourclassname); // display information about this" "} // initialize the selector and the corresponding function-(void) selfuncs {[self dowithcattleid: cattle [0] colorparam: @ "brown"]; [self dowithcattleid: cattle [1] colorparam: @ "red"]; [self dowithcattleid: cattle [2] colorparam: @ "black"]; [self dowithcattleid: Self colorparam: @ "Haha"]; // a heterogeneous self (that is, doproxy itself) is intentionally input here ), doproxy is certainly not bull or cattle} // function pointer test-(void) functionpointers {// The first way to get the function pointer setskincolor_func = (void (*) (ID, se L, nsstring *) [cattle [1] methodforselector: Skin]; // The preceding statement is actually equivalent to the following method: // imp setskincolor_func = [cattle [1] methodforselector: skin]; // use the second method to obtain the saysomething function pointer say_func = [cattle [1] methodforselector: Say]; // call setskincolorsetskincolor_func (cattle [1], skin, @ "verbose"); nslog (@ "running as a function pointer will be more efficiency! "); // Call the saysomething method say_func (cattle [1], say);} @ end
Test the main function main ()
# Import <Foundation/Foundation. h> # import "doproxy. H "int main (INT argc, const char * argv []) {ngutoreleasepool * Pool = [[ngutoreleasepool alloc] init]; doproxy * doproxy = [doproxy new]; [doproxy setallivars]; [doproxy selfuncs]; [doproxy functionpointers]; [doproxy release]; [pool drain]; return 0 ;}
Running result:
21:40:33. 240 helloselector [630: a0f] running in the method of dowithcattleid: colorparam:
21:40:33. 245 helloselector [630: a0f] Hi, I am a cattle, have not setskincolor!
21:40:33. 247 helloselector [630: a0f] Hello, I am a cattle, I have 4 legs.
21:40:33. 248 helloselector [630: a0f] Hello, I am a Red Bull, I have 4 legs.
21:40:33. 250 helloselector [630: a0f] Hello, I am a black bull, I have 4 legs.
21:40:33. 251 helloselector [630: a0f] Hi, you are a doproxy, but I like cattle or bull!
21:40:33. 252 helloselector [630: a0f] running as a function pointer will be more efficiency!
21:40:33. 254 helloselector [630: a0f] Hello, I am a verbose bull, I have 4 legs.