------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
核心语法
一、点语法
点语法就是setter方法与getter方法的另一种写法,直接简化了而已。当然,方法还是需要声明和实现,并无差别,只是在使用的时候将写法改变了。
一般情况下,要调用getter和setter方法如下:
//set方法
Person *p = [Person new];
[p setAge: 10];
//get方法
int a = [p age];
唯一需要注意的是,在实现setter与getter方法的时候不能使用点语法,否则容易出现死循环。
死循环注意:
-(void) setAge:(int) age {
// 下面的代码会引发死循环(因为循环调用了 [self setAge:age])
self.age=age;
}
-(int) age{
// 下面的代码会引发死循环(因为循环调用了 [self age])
return self.age;
}
@public:任何地方都能直接访问对象的成员变量
@private:只能在当前类的对象方法中直接访问
@protected:能在当前类和子类的对象方法中直接访问
二、成员变量的作用域
四种作用域,在变量声明之前的修饰词就代表着这个成员变量的作用域。
@public(公用的):在程序的任何地方都可以访问该变量。
@protected(保护的):只有在当前类及其子类可以访问,在没有修饰词的情况下,变量的作用域默认为是@protected。
@private(私有的):只有在当前类可以访问该变量。
@package(打包的):在框架内可以访问该变量。
三、@property和@synthesize
1> @property用在@interface中,可以自动生成某个成员变量的setter 和getter的声明和实现
@property int age;
// 相当于 -(void) setAge :(int)age;
// -(int)age;
2> @synthesize用在@implementation中,可以自动生成某个成员变量的setter和getter的实现
@synthesize age=_age
// 相当于
-(void) setAge:(int)age;
{
_age = age;
}
-(int)age
{
return _age;
}
@property和@synthesize都是自动生成变量以及其setter、getter方法的关键字。
@property是声明了一个变量,并且声明了这个变量的setter方法和getter方法,而@synthesize则是实现这个变量的setter与getter方法。使用情况如下:
@interface Student : NSObject
@property int number;
@end
@implementation Student
@synthesize number = _number;
@end
而在实现中的“@synthesize number = _number;“这一句省略也并无影响。需要注意的是:使用@property声明和实现的变量其作用域为private,只能在当前类可以访问,同时可以生成该变量的setter方法、getter方法的声明和实现。而当同时使用@property和@synthesize时,其效果与只用@property无差,只是使用@synthesize在实现的时候可以自定义生成变量名称。
另外,只有使用了@property,才会生成作用域为private的_age变量,@synthesize改变这个变量的名称。当我们声明了变量名称时,使用@property,可以自动生成这个变量的setter方法与getter方法,当我们只实现了这个变量的setter方法时,@property会自动生成这个变量的getter方法以及带下划线的成员变量,实现了getter方法时,自动生成的是setter方法以及带下划线的成员变量,但是,如果自己实现了setter方法与getter方法,就不会生成带下划线的成员变量,需要手动。
四、构造方法
通常我们通过new方法来新建一个对象,但是new作为系统自带的方法并不会将新建的对象初始化。生成对象分为两步,alloc方法给对象分配内存空间,init方法将对象的成员变量初始化为默认值。
1:若想某个对象一创建出来,它的成员变量就是某个值(10),就重写构造方法
- (id) init
{
if(self = [ super init ]) //先调回super的init方法,如果对象初始化成功
{
_age=10 //赋值
}
return self; //返回初始化完毕的对象
}
自定义构造方法
规范:(1)一定是对象方法,以 - 开头
(2)返回值一般都是id类型
(3)方法名一般以initwith开头
-(id)initwithName:(NSString*)name
{
if(self=[super init]) //先调回super的init方法,如果对象初始化成功
{
_name=name //赋值
}
return self; //返回初始化完毕的对象
}
Person *p = [Person new];
等同于
Person *p = [[Person alloc] init ];
而初始化有一个固定的格式,在实现的时候使用,如下
@implementation Person
- (id)intWithAge : (int)age
{
if( self = [super init] ){
_age = age;
}
return self ;
}
@end
3:NSLog输出
NSLog(@"%p",&p) // 指针变量的地址
NSLog(@"%p",p) // 对象的地址
NSLog(@"%@",p) // 类名:对象地址
NSLog(@"%d",_ _LINE_ _) // 输出当前行号
NSLog(@"%s",_ _FILE_ _) // 输出文件路径
NSLog(@"%s\n",_ _func_ _) //输出所在函数名
NSLog输出语言字符串的时候,不能有中文
五、分类
分类用于不改变原类的基础上增加一些方法,只是方法,并不包含成员变量,但分类可以访问原类的成员变量。主要用于系统自带的类,因为自定义的类可以直接通过继承增加方法,一般以分类的作用作为名称。格式如下
Student +Monito.h
//首先包含原类,以学生类为例
#import"Student.h"
//声明一个班长类
@interface Student (Monito)
//为班长添加管理方法
-(void)manage;
@end
Student +Monito.m
//包含分类声明
#import "Student+Monito.h"
@implementation Student(Monito)
//实现管理方法
- (void)manage
{
NSLog(@"班长整治秩序");
}
@end
进行以上的声明和实现后,主函数内包含分类的头文件就能调用分类实现的方法了。而当分类与原类、原类的父类有重名的方法时,调用的优先级为:分类→→原类→→父类,而当多个分类也有同名函数时,按照编译顺序,最后编译的分类最先调用。