————————Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ———————
本文将会总结一些OC特有的一些核心语法,比如点语法、@property和@synthesize、id等等语法。
一、点语法
OC中的点语法与Java中的点语法不同,不是代表访问类中的相应成员变量的,在OC中是表示转为相应的get方法和set方法的。只要记住这一句话,那么点语法就迎刃而解了。
我们举个例子说明一下点语法的作用:
@interface Person : NSObject
{
int _age; //年龄
}
//getter和setter的声明
- (void)setAge:(int)age;
- (int)age;
@end
@implementation Person
//getter和setter的实现
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
@end
int main()
{
//创建新的对象
Person *p = [[Person alloc] init];
//利用点语法给成员变量_age赋值
p.age = 10;
int a = p.age;
NSLog(@"人的年龄为%d,%d岁", p.age, a);
return 0;
}
其中main函数中的p.age = 10;就等于[p setAge:10];,编译器就把它翻译成set语句。同理,int a = p.age;就等于int a = [p age];
二、成员变量的作用域
有四种情况,分别为@public、@private、@protected和@package。
这四种情况都可以写在定义成员变量时的前面,不过请注意,当写了一种以后,如果不写其他的关键字,那么默认之后全是这一种作用域作用。
@public : 在任何地方都能直接访问对象的成员变量
@private : 只能在当前类的对象方法中直接访问(@implementation中默认是@private)
@protected : 可以在当前类及其子类的对象方法中直接访问 (@interface中默认就是@protected)
@package : 只要处在同一个框架中,就能直接访问对象的成员变量
注意:
@interface中默认就是@protected,也就是说在@interface中定义的成员变量,如果不加任何关键字修饰的话,那么这些成员变量只能在当前类以及子类的对象方法中访问,其他的均不可以直接通过成员变量名访问。
@implementation中默认是@private,也就是说在@implementation中定义的成员变量,如果不加任何关键字修饰的话,那么这些成员变量只能在当前类的对象方法中访问,其他的均不可以直接通过成员变量名访问。
另外,@interface和@implementation中不能声明同名的成员变量
因此我们一定要注意成员变量定义时的作用域,以免在编程中造成不必要的麻烦。
理解误区:
当类中又@private的成员变量时,该类的子类是不能直接在.m文件中直接访问的,但是要明白的是,不能直接访问与没有这个成员变量是两码事。也就是说子类中是由@private的成员变量的,只是不能直接调用而已。因为根据继承原理,我们知道,继承就是子类拥有父类所有的属性与方法,包括了成员变量!
补充:
1)程序中不写@interface在语法上是可以的,但一般我们都要写声明,这样才让人一眼就能看明白。
2)如果把@implementation中的成员变量写在调用它的main函数之前,并且定义上@public作用域,那么main函数也是可以调用的。要特别记住这两个条件,(1)在调用之前定义,(2)要定义上@public
三、@property和@synthesize
@property和@synthesize是帮助我们自动生成set方法和get方法的。
1.@property——自动生成某个成员变量的set和get方法声明
@property int age;
就相当于
- (void)setAge:(int)age;
- (int)age;
这是编译器的一种特性,当读取到@property代码时,它就会按照声明的方法翻译来代替代码。
2.@synthesize是帮助我们自动生成set方法和get方法实现的,并且会访问等于号右边的这个成员变量。
@synthesize age = _age;
这句的意思是,要把property中的age进行实现,_age代表实现中是访问_age。
就相当于
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
注意:如果只写
@synthesize age;
那么访问的就不是_age,而是age,特别要注意这一点!
3.set方法和get方法的最简写法
@property int age;
只写@property,不写@synthesize,这样也是可以的。那么这里@property做了3件事情:
1)生成getter和setter的声明
2)生成带_age的一个成员变量
3)生成getter和setter的实现
这样虽然极大的简化了程序。但是也有缺点,就是只写@property生成的成员变量是@private的作用域,成员变量私有了,子类是不能直接访问的,只能通过getter和setter来访问。
总结:
1.@property用在@interface中,用来自动生成setter和getter的声明;
2.@synthesize用在@implementation中,用来自动生成setter和getter的实现;
3.@synthesize的细节
1)@synthesize age = _age; setter和getter实现中会访问成员变量_age,如果成员变量中_age不存在,就会自动生成一个@private成员变量_age;
2)@synthesize age; setter和getter实现中会访问成员变量age,如果成员变量age不存在,就会自动生成一个@private成员变量age;
3)手动实现:如果手动实现了setter,编译器就只会自动生成getter,若无成员变量也生成;如果手动实现了getter,编译器就只会自动生成setter,若无成员变量也生成;如果手动实现了setter和getter,编译器就只不会自动生成不存在的成员变量。注意:也就是说如果setter和getter都有了,但没有定义成员变量,那么就会报错。
四、id类型
id是万能指针,相当于NSObject *(也就是说id后面不能再跟*了),能指向任何OC对象。
举一个id的应用场景:
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property int age;
@property id obj;
@end
Person.h
import "Person.h"
@implementation Person
@end
main.m
#import <Foundation/Foundation.h>
#import "Person.h"
void test(id d)
{
}
int main(int argc, const charchar * argv[])
{
@autoreleasepool {
Person *p = [Person new];
NSObject *o = [Person new];
id d = [Person new];
[d setAge:10];
[d setObj:@"321423432"];
NSLog(@"%d", [d age]);
}
return 0;
}
注:id后面不加*。学习小感悟:
OC中像几种小语法还是比较多的,但是只要抓住每一个关键字的本质特性,那么也会觉得还是挺简单的,我们要熟记这些语法。这些语法可能总结的不是很全面,之后有新的OC特有语法我再加进博客当中。