I'm doing research about Objective-C, and I'd like to know if it has th开发者_如何学JAVAe concept of reflection. None of the documents I've found so far describes reflection.
There are runtime functions described in Runtime Reference which allows not only querying for features of a class or an instance, but also adding a method, or even creating a new class at runtime. I say this is a very dynamic kind of reflection, which was not usually available to C-based languages. Mike Ash's wrappers is an Objective-C wrapper around that. Again, it can even add methods! The base class of Cocoa, NSObject
, also provide wrappers for many of the runtime functions, see NSObject
protocol reference. For example
[foo respondsToSelector:@selector(bar:)];
if([foo isKindOfClass:[NSString class]]){ ... }
does what the method names say. You can even add a method on the fly. For example,
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface Foo:NSObject
{
}
@end
@implementation Foo
-(void)sayHi
{
NSLog(@"Hi! from %@",NSStringFromSelector(_cmd));
}
+(BOOL)resolveInstanceMethod:(SEL)sel
{
Method method=class_getInstanceMethod(self,@selector(sayHi));
class_addMethod(self,sel,method_getImplementation(method),method_getTypeEncoding(method));
return YES;
}
@end
int main(){
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc] init];
Foo* foo=[[Foo alloc] init];
[foo aeiou];
[foo bark];
[foo mew];
[pool drain];
return 0;
}
This produces the output
Hi! from aeiou
Hi! from bark
Hi! from mew
What it does is as follows:
SEL
is the variable which represents the sent message (or method call, in the other terminology.)- Objective-C runtime calls
resolveInstanceMethod:
of a class if a message sent to an instance is not implemented in the class - So, in this case, I just copy an implementation of a predefined method called
sayHi
to that method's implementation. - From the method, you can use
_cmd
to see what was the selector used in calling the method. So, even from a singlesayHi
implementation, we can get different output.
Some of the standard Cocoa's implementation (Key-Value-Coding, Key-Value-Observing and Core Data in particular) uses the runtime to dynamically modify the class.
Yes, Objective-C has reflection (and abstract classes). Whether that reflection fits your needs or not is a different question.
Reflection in Objective-C is surprisingly flexible for a C derived language. You can ask a class what methods it implements or you can modify and/or add methods to existing classes. You can even create new classes on the fly or change the class of any instance at any time.
A typical Objective-C program does none of theses things (at least not directly) save for occasionally calling respondsToSelector:
or conformsToProtocol:
. While Objective-C is a fully dynamic, reflective, object oriented language, that doesn't mean that such patterns are encouraged or typically used.
You might find my answers to these questions interesting:
In Objective C, how to find out the return type of a method via reflection?
Does Objective-C have a Standard Library?
Smalltalk runtime features absent on Objective-C?
And, of course, the runtime is very well documented. As is the language. Or you could read the source.
I guess I don't know what aspect of reflection you're looking for. Are you looking for how to determine which class a given variable is? If so, check this out: Objective-C class -> string like: [NSArray className] -> @"NSArray"
// Get a object's class name
if ([NSStringFromClass([foo class]) compare:@"NSSomeObject"] == NSOrderedSame) {...}
// Does an object have a method
[foo respondsTo:@selector(method:)]
Are you looking for more than just this?
There are a flock of methods that can access various properties of a class and, presumably, "peek" and "poke" at some object internals. I've never played with them, and a little reading that I've done suggests that they're far from perfect, but they do appear to offer some ability for "reflection", similar to the Java concept.
精彩评论