成员变量
什么是成员变量
成员变量指的是在类接口部分或类实现部分定义的变量,oc中成员变量都是实例变量。
成员变量类似于c语言中的结构体,下面实现了中类接口部分定义成员变量:
#import <Foundation/Foundation.h>
@interface FKPerson : NSObject {
//下面定义了两个成员变量
@private
NSString* _name;
int _age;
}
// 下面定义了一个 setName: 方法
- (void) setName: (NSString*) name;
// 获取name
- (NSString*) name;
// 提供方法设置age成员变量
- (void) setAge: (int) age;
// 获取age
- (int) age;
@end
注意的点:当我们定义成员变量时应该以下划线开头。
如何访问实例变量
1.直接访问
只要实例存在,程序就可以访问该成员变量,
oc提供了直接访问成员变量的语法:
实例->实例变量
例如访问上面定义的成员变量_name
代码如下:
#import "FKPerson.h"
int main(void) {
@autoreleasepool {
FKPerson *p1 = [[FKPerson alloc] init];
p1->_name = @"李刚";
NSLog(@"name: %@", p1->_name);
}
}
但此时程序会报错,虽然我们使用了正确的语法p1->_name,但在我们的类接口部分我们使用了@private指令,所以无法直接访问,我们应该将指令修改成@public即可使用直接访问。
2.使用自己定义的实例方法
当我们给成员变量使用@protected或者@private时无法在主函数中直接访问成员变量,这时我们可以利用自己定义的方法,接下来,自己定义实例方法非常简单,就是在类接口部分声明方法,在实现部分完成定义即可。实现代码如下所示:
#import "FKPerson.h"
@implementation FKPerson
// 提供方法来设置name成员变量
- (void) setName:(NSString *) name {
//检查合理性,要求用户名必须在2-6位之间
if ([name length] > 6 || [name length] < 2) {
NSLog(@"您设置的人名不符合要求");
return;
} else {
_name = name;
}
}
// huoqu name
- (NSString*)name {
return _name;
}
// 提供方法来设置age成员变量
- (void) setAge: (int) age {
if (_age != age) {
//检查合理性,要求age必须在0-100位之间
if (age > 100 || age < 0) {
NSLog(@"您设置的年龄不合法");
return;
} else {
_age = age;
}
}
}
- (int) age {
return _age;
}
@end
代码中的age和name就是我们定义的方法。
就可以在主函数中调用了:
int main(void) {
@autoreleasepool {
FKPerson *p1 = [[FKPerson alloc] init];
[p1 setAge:18];
[p1 setName: @"李刚"];
NSLog(@"name: %@, age: %d", [p1 name], [p1 age]);
}
}
3.点方法
当一个成员变量有getter 和 setter方法时,即可运用点方法调用,点方法的实质就是调用setter和getter方法。
例如修改上面的成员变量代码如下:
int main(void) {
@autoreleasepool {
FKPerson *p1 = [[FKPerson alloc] init];
p1.age = 19;
p1.name = @"ligang";
NSLog(@"name: %@, age: %d", [p1 name], [p1 age]);
}
}
点方法和我们创建的方法一样,是可以在不同指令下访问成员变量的。
成员变量的一些运行机制
成员变量无需显式初始化,只要为一个类定义了实例变量,系统会默认初始化实例变量,基本类型的成员变量被默认为0,指针变量被默认为nil(空指针类型类似于c语言NULL)。
例如上面代码中我们定义的对象p1,如果不对其成员变量_age赋值,那么我们在输入其时值为0.
单例(Singleton)模式简介
单例模式主要用于反复创建,销毁同一个类的程序。
创建一个始终只能创建一个实例的单例类,可以提高程序的性能。
如何实现单例类
单例类可通过static全局变量实现,程序考虑定义一个static全部变量,该变量用于保护已经创建的SIngleton对象——每次程序需要获取该实例时,首先会判断static全局变量是否为nil,如果该全局变量为nil,则会初始化一个实例并赋值给static全局变量。
下面是实现一个单例类的代码。
首先是类接口部分:
#import <Foundation/Foundation.h>
@interface FKSingleton : NSObject
// 声明一个类方法允许程序通过该方法获得该类的唯一实例
+ (id) instance;
@end
类实现部分:在类实现部分我们利用了一个static全局变量,在最开始我们没有创建实例时,它的值为nil。
这里介绍一下static的简单用法:
1.可以修饰局部变量,将局部变量存储到静态存储区。
2.可以修饰全局变量,限定全局变量只能在当前源文件中访问。
3.可以修饰函数,限定该函数只能在当前源文件调用。
这里static的作用是:类方法不可以访问实例变量,通过static修饰的实例变量 ,可以被类方法访问。
#import "Singleton.h"
static id instance = nil;
@implementation FKSingleton
+ (id) instance {
// 如果instance为nil
if (!instance) {
// 创建一个Singleton实例,并将该实例赋给instance全局变量
instance = [[super alloc] init];
}
return instance;
}
@end
主函数:
int main(void) {
@autoreleasepool {
// 判断两次获取的实例是否相等,若相等则程序返回一
NSLog(@"%d", [FKSingleton instance] == [FKSingleton instance]);
}
}
在第一次调用类方法时,此时的全局变量值为id,进入if语句执行语句创建了一个实例对象,当第二次调用类方法时,全局变量已经不为空,而是第一次创建的对象,所以输出结果是1.
这里我们用到了关键字:super
1、直接调用父类中的某个方法
2、super处在对象方法中,那么就会调用父类的对象方法
super处在类方法中,那么就会调用父类的类方法
3、使用场合:子类重写父类的方法时想保留父类的一些行为