成员变量作用域:
- @public:在任何地方都能直接访问对象的成员变量
- @protected:能在当前类和子类的对象方法中直接访问(默认)
- @private:能在当前类的对象方法中直接方法,子类不能;
- @package:同一个“体系内”(框架)可以访问,介于@public和@private之间
注意:
- 虽然父类中的私有的成员变量(private修饰的变量),不能在子类的方法中通过变量直接访问,但是子类内部还是有那个变量,只能通过set方法和get方法访问。
- 在.m (实现文件)中申明的成员变量默认是私有的
@implementation Person
{
int _age;//默认是私有的成员变量
}
//注意:在.m文件中定义的成员变量不能和.h文件中定义的成员变量同名
- 在implementation中定义的成员变量,在子类中也有这个成员变量
@property和synthesize
下面以一个Person类的代码为例子
在.h文件中
@interface Person : NSObject
{
int _age;
NSString *_name;
}
@property int age;
@property NSString *name;
@end
表示声明了2个属性: 年龄:_age、名字:_name, (用@property)默认生成2个对应的 setter 和 getter 方法。
@synthesize帮助我们自动实现get和set方法,告诉它是给哪个成员变量,在后面加上 =成员变量。
在.m文件中
@implementation Person
@synthesize name = _name; //会访问_name这个变量
@synthesize age = _age;
@end
表示实现2个 setter 和 getter 方法,其中 age = _age 表示说在 getter 和 setter 方法中操作的实力变量是_age,如果省略了 = _age, = _name, 那么会在. h 文件中生成同名的实例变量 age,name(注意:这里并没有下划线),此时生成的 setter 和 getter 方法所操作的实例变量是 age,name, 所以_age,_name 并没有被操作.
在 ios5.0后,@synthesize也可以省略不写,此时在. h 文件中只写@property 即可,编译器会自动生成相应的实例变量,实例变量的名字是属性名称前加下划线.
@synthesize连着写:
@synthesize age = _age,name = _name;
@property连着写:
@property NSString *name,*sex;
//@property连着写需要注意:必须是同一类型的,若写成下面的代码,则编译器会报错:
@property int age,NSString *name;
最简单的一步骤申明成员变量和get,set方法的申明、实现
@property int age; //会生成成员变量_age,并且访问
//缺点:成员变量是私有的,子类不能直接访问
synthesize 不加 = 成员变量
//在.m文件中
@synthesize age;
//默认会访问age这个成员变量,而不是_age,如果没有age,就会自动生成@private类型的age变量。
@property 特性
- 自从xcode 4.4后,@property就独揽了@synthesize的功能,也就是说,@property可以同时生成setter和getter的申明和实现。
- 生成的原则:没有才帮你生成。比如:在.m文件中有setter方法而没有getter方法,则只会生成getter方法。
- @property int age; 若在.h文件的interface中没有申明 int _age,若通过@property生成setter或getter任一个方法。都会生成一个@private的 int _age;若没有通过@property生成任意一个setter或者getter方法,则不会生成@private的 int _age。
id
id:可以理解成是万能指针,指向\操作任何oc对象。还可以理解成 id = NSObject *
有一个Person类,创建Person对象,可以用以下的三个方法
Person *p = [Person new];
NSObject *o = [Person new];
id id1 = [Person new];
重写init方法(构造方法)
//返回类型可以用id,但最好用instancetype
- (id)init{
//1、一定要调用super的init方法,初始化父类中申明的一些成员变量和其他属性
//2、再进行本类的成员变量的初始化
//3、return self
self = [super init]; //返回当前对象
if (self != nil) {
_age = 23;
}
return self; //返回一个已经初始化完毕的对象
}
重写构造方法的注意点:
- 先调用父类的构造方法( [super init] )
- 再进行子类内部成员变量的初始化
自定义构造方法
自定义构造方法的规范:
- 一定是对象方法,一定要以 -开头
- 返回值一般是id类型
- 方法名一般以 init 开头
//重写构造方法例子:
//在.m文件中
- (id)initWithName:(NSString *)name{
if (self = [super init]) {
_name = name;
}
return self;
}
调用自定义的构造方法
Person *p = [[Person alloc]initWithName:@"chenfanfang"];
自定义构造方法中,若要初始化的成员变量属于父类中的成员变量,可以用点语法(即调用父类中的set方法来实现)
-(id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no{
if (self = [super init]) {
_no = no;
self.name = name; //即[self setName:name];
self.age = age; //即[self setAge:age];
}
return self;
}
注:以上的构造方法的重写的例子在开发中不常见,常见的是以下的例子:
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no{
if (self = [super initWithName:name andAge:age]) {
_no = no;
}
return self;
}