Dynamic Typing and Dynamic Binding
Dynamic typing defers the determination of the class that an object belongs to until the program is executing.
Dynamic binding defers the determination of the actual method to invoke on an object until program execution time.
id can be used for storing objects that belong to any class. The real power of this data type is exploited when it's used this way to store different types of objects in a variable during the execution of a program.
The Objective-C system always keeps track of the class to which an object belongs. It also lies the concepts of dynamic typing and dynamic binding ——that is, the system makes the decision about the class of the object and therefore, which method to invoke dynamically, at runtime instead of at compile time.
因为dynamic typing 和 dynamic binding,method在执行而不是编译时被触发,所以下面的代码可以正确执行,而不用担心在不同class的 print 混淆使用,可避免编译器不知该调用哪个print的问题。
int main (int argc, char * argv[])
{
@autoreleasepool{
id dataValue;
Fraction *f1 = [[Fraction alloc] init];
Fraction *c1 = [[Complex alloc] init];
[f1 setTo: 2 over: 5];
[c1 setReal: 10.0 andImaginary: 2.5];
//fist dataValue gets a fraction
dataValue = f1;
[dataValue print];
//now dataValue gets a complex number
dataValue = c1;
[dataValue print];
}
return 0;
}
id dataValue = [[Fraction alloc] init];
[dataValue setReal: 10.0 andImaginary: 2.5];
在编译时不会有错误信息报出,当我们run this program containing these lines 的时候会报错,程序中止。
为什么我们不把所有的objects type设成id ?
When you define a variable to be an object from a particular class, you are using what's known as static typing. When you use static typing, the compiler ensures, to the best of its ability, that the variable is used consistently throughout the program.
It's better to get your error out during the compilation phase of your program than during the execution phase. If you leave it until runtime, you might not even be the one running the program when the error occurs.
Another reason for using static typing is that it makes your programs more readable.
You cannot use the dot operator with id variables, the compiler will give you an error if you do so.
If a method with the same name is implemented in more than one of your classes, each method must agree on the type of each argument and the type of value it returns so that the compiler can generate the correct code for your message expressions.
Objective-C always uses dynamic binding: determining the exact implementation of a request based on both the request (operation) name and the receiving object at the run-time.
The null object pointer:
nil explicitly:
if (person == nil)
return;
nil implicitly:
if (! person)
return; //当person==nil 时,!person为真,if 语句执行
nil can use in assignments and as arguments if expected.
person = nil;
[person name];
Class introspection:
You can ask an object about its class:
Class myClass = [myObject class];
NSLog (@"My class is %@", [myObject className]);
Testing for general class membership (subclasses included):
if ([myObject isKindOfClass: [UIControl class]]){
//something
}
Testing for specific class membership (subclasses excluded):
if ([myObject isMemberOfClass: [NSString class]]){
//something string specific
}
Identity versus Equality:
Identity —— testing equality of the pointer values
if (object1 == object2){
NSLog (@"Same exact object instance");
}
两个object 指针指向地址一样,即为同一个object.
Equality —— testing object attributes
if ([object1 isEqual: object2 ]){
NSLog (@"Logically equivalent, but may be different object instances");
}
两个object 的内容完全一致,但是它们可能不是同一个object,即指向地址不同,两个object.