------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1、self和super 关键字的介绍
1, self 和 super 简介
在 C++ 和 C# 等高级面向对象的语言中,有一个 this 指针用来描述当前对象。 在 OC 中同样也有 self 表示当前对象, 与 C++ 语言中的 this 指针含义一样。
在 OC 中, 提供了两个保留字, 一个是 self, 另一个是 super。
在实例方法中, self 就是当前对象,给 self 发送消息, 即给当前对象发送消息,调用方法给 super 发送消息,则是给其父类发送消息,调用父类的方法。
2, self 的应用场景
1) 使用在类方法中
2)使用在实例方法中
3)访问成员变量
4)在 OC 内存管理中有特殊用法
2、self 在实例方法中的使用
1, 在实例方法中表示当前对象
在实例方法中, self 就是当前对象,使用对象允许访问实例变量或其他实例方法。
2, 在实例方法中调用另一个实例方法
例如有一只狗, 即创建一个 Dog 类。 然后,它有叫的方法(bark),也有吃的方法(eat)。
那么实现,当狗吃完东西后就叫,来提示吃完了。
@interface Dog : NSObject
- (void)bark;
- (void)eat;
@end
@implementation Dog
- (void)bark {
NSLog(@"汪汪汪, 吃完了...");
}
- (void)eat {
NSLog(@"吃狗粮...");
[self bark];
}
@end
在eat实例方法中利用self调用bark这个实例方法,实现了狗吃完东西就叫表示吃完了这个功能。
3, self 就是当前对象
@interface Dog : NSObject
- (void)bark;
- (void)eat;
@end
@implementation Dog
- (void)bark {
NSLog(@"汪汪汪, 吃完了...");
NSLog(@"bark 中 self 地址为 %p", self);
}
- (void)eat {
NSLog(@"吃狗粮...");
[self bark];
NSLog(@"eat 中 self 地址为 %p", self);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Dog *dog = [[Dog alloc] init];
[dog eat];
NSLog(@"dog 的地址为 %p", dog);
}
return 0;
}
运行的结果为:在运行结果中self和dog的地址是一样的,即self就是当前对象。
3、self 在类方法中的使用
1, self 在类方法中含义与在实例方法中不一样
可以添加一个类方法, 在类方法中打印出 self 的数据,发现与对象的地址完全不同(实际上,没有必要打印,思考一下,类方法是与对象实例无关的,当然无法打印地址)。
在实例方法中,self 表示的实际上是当前类。换句话说,利用 self 可以在类方法中调用其他类方法。
2, 使用 self 调用类方法
既然 self 就是类,那么调用类方法,就是对 self 发送消息
@interface MyClass : NSObject
+ (void)method1;
+ (void)method2;
@end
@implementation MyClass
+ (void)method1 {
NSLog(@"我是类方法 method1");
}
+ (void)method2 {
NSLog(@"我是类方法 method2");
[self method1];
}
@end
在类方法method2中self调用了类方法method 1,实现了用self来调用类方法。
4、self 修饰变量
1, 问题的引出
如果类中提供的实例变量与其 setter 方法中提供的参数名一样,如何处理赋值呢?
下面引入一个案例,假设有一个 Dog 类,里面提供一个实例变量 _speed 表示速度,然后
@interface Dog : NSObject {
int _speed;
}
- (int)speed;
- (void)setSpeed:(int)speed;
@end
@implementation Dog
- (int)speed {
return _speed;
}
- (void)setSpeed:(int)speed {
_speed = speed;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Dog *dog = [[Dog alloc] init];
[dog setSpeed:120];
NSLog(@"小狗以 %d 的速度冲了出去", [dog speed]);
}
return 0;
}
运行为:小狗以120的速度冲了出去
当 setter 方法中参数名也是 _speed 时,修改 setter 方法
- (void)setSpeed:(int)_speed {
_speed = _speed;
}
运行的结果为:小狗以 0 的速度冲了出去
这个时候问题出现了,两次小狗出去的速度不一样,也就是说并没有被赋以速度值。
2, 分析
在方法中,声明的参数 _speed 是局部变量,它隐藏了全局作用的 实例变量,因此无法获得数据,所赋值也没有作用到实例变量中。
3, 改用 self 引用该变量
修改 setter 方法
- (void)setSpeed:(int)_speed {
self->_speed = _speed;
}
运行结果为:小狗以120的速度冲了出去
通过对比知道可以利用self来修饰变量获得数据完成赋值。