一、点语法
1、认识点语法
声明一个Person类
@interface Person : NSObject
{
int _age;
}
- (void)setAge:(int)age;
- (int)age;
@end
Person类的实现
implementation Person
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
@end
使用点语法来存取数据
#import <Foundation/Foundation.h>
#import "Person.h"
int main()
{
Person *p = [Person new];
p.age = 10; // 该语句在编译的时候会被替换为[p setAge:10];
NSLog(@"age=%d",p.age); <span style="white-space:pre"> </span>// p.age在编译的时候会被替换为[p age];
return 0;
}
2 、点语法的作用
OC设计点语法的目的,是为了让其他语言的开发者可以很快的上手OC语言开发,使用点语法,让它和其他面向对象的语言如java很相像。
点语法的本质是方法的调用,而不是访问成员变量,当使用点语法时,编译器会自动展开成相应的方法,如果没有set和get方法,则不能使用点语法。例如:
p.age = 10 展开为:[p setAge:10]
p.age 展开为:[p age]
当有赋值时,编译器会将其展开为setter方法,否则展开为getter方法。在OC中访问成员变量只有一种方式即使用-> 如p->age,这种情况要求在@public的前提下。
4、点语法的使用注意
例如下面的使用方式是一个死循环:
(1)在set方法中,self.age=age;相当于是[self setAge:age];
(2)在get方法中,return self.age;相当于是[self age];
二、成员变量作用域
1、作用域类型
(1)@public : 在任何地方都能直接访问对象的成员变量
(2)@private : 只能在当前类的对象方法中直接访问(@implementation中默认是@private)
(3)@protected : 可以在当前类及其子类的对象方法中直接访问 (@interface中默认就是@protected)
(4)@package : 只要处在同一个框架中,就能直接访问对象的成员变量
2、使用注意
(1)在类的实现即.m文件中也可以声明成员变量,但是因为在其他文件中通常都只是包含头文件而不会包含实现文件,所以在这里声明的成员变量是@private
(2) @interface和@implementation中不能声明同名的成员变量。
(2)在@interface @end之间声明的成员变量如果不做特别的说明,那么其默认是protected的。
(3)一个类继承了另一个类,那么就拥有了父类的所有成员变量和方法,注意所有的成员变量它都拥有,只是有的它不能直接访问。
示例代码:
@public // 在任何地方都能直接访问对象的成员变量
int _age;
@private // 只能在当前类的对象方法中直接访问
int _height;
@protected // 能在当前类和子类的对象方法中直接访问
int _weight;
三、@property的使用
(1)@property会在编译的时候自动为成员变量生成setter和getter的声明和实现方法
例如:@property int age;
(2)@synthesize会在编译的时候为成员变量自动生成setter和getter的实现方法,如果没有定义该成员变量,则会自动生成@private类型的变量
例如:@synthesize age = _age;
四、id类型
(1)id为Object-C对象的通用类型,也就是说可以用id来指向何对象
例如:id p = [Person new];
(2)id定义在运行期数据库的头文件里面,如下:
typedef struct obje_object{
Class isa;
} *id
(3)由于id在定义时就已经是指针类型,所以指向对象时不用加“*”。
五、构造方法
(1)当程序要创建一个可用对象时,需要调用+alloc方分配内存,再调用-init方法对该对象进行初始化。
例如有个Person类:Person *p = [[Person alloc] init];
(2)为了让成员变量在对象创建出来的时候具有一些固定的值,就需要重写构造方法
代码示例:
@implementation Person
- (id)init
{
// 调用父类的init方法赋值给该对象,使得该对象具备与NSObject相同得初始化对象的能力,同时判断该对象是否为空
if (self = [super init]) {
_age = 10;
}
//返回该对象
return self;
}
@end
方法调用:
#import <Foundation/Foundation.h>
#import “Person.h”
int main()
{
//调用父类的alloc方法为对象分配存储空间,再调用init初始化对象
Person *p = [[Person alloc] init];
NSLog(@"age=%d",p.age);
return 0;
}
(3)自定义构造方法
@implementation Person
- (id)initWithName:(NSString *)name
{
if (self = [super init]) {
_name = name;
}
return self;
}
- (id)initWithName:(NSString *)name andAge:(int)age
{
if (self = [self initWithName:name]) {
_age = age;
}
return self;
}
@end
方法调用:
#import <Foundation/Foundation.h>
#import “Person.h”
int main()
{
Person *p = [[Person alloc] initWithName:@"cx"];
NSLog(@"name=%@",p.name);
Person *p1 = [[Person alloc] initWithName:@"wj" andAge:10];
//NSLog(@"name=%@,age=%d",p1.name,p1.age);
NSLog(@"name=%@",p1);
return 0;
}
六、分类-Categroy
(1)分类的作用
在不改变原来类模型的前提下,可以使用分类来扩充方法,通过分类可以将一个庞大的类分模块开发有利于团队合作。
(2)分类的声明
<span style="font-size:18px;">@interface 类名 (分类名称)
// 方法声明
@end
</span>
(3)分类的实现@implementation 类名 (分类名称)
// 方法实现
@end
代码示例:/*
给NSString增加一个类方法:计算某个字符串中阿拉伯数字的个数
给NSString增加一个对象方法:计算当前字符串中阿拉伯数字的个数
*/
@implementation NSString (wj)
- (int)characterNumberOfString
{
return [NSString characterNumberOfString:self];
}
+ (int)characterNumberOfString:(NSString *) str
{
int count = 0;
unichar c;
for (int i = 0; i<str.length; i++) {
//取出i位置的字符
c = [str characterAtIndex:i];
if (c >= '0' && c <= '9') {
count++;
}
}
return count;
}
@end
分类的调用
#import <Foundation/Foundation>
#import “Person.h”
#import “Person+wj.h”
int main()
{
Person *p = [[Person alloc] init];
p.age = 10;
[p test1];
//字符串也是一个对象,调用自身的方法来计数
int num = [@"fs3323df32" characterNumberOfString];
int num1 = [NSString characterNumberOfString:@"12345abcd"];
NSLog(@"num=%d,num1=%d",num,num1);
return 0;
}
(4)分类使用注意
a、Category可以访问原始类的实例变量,但不能添加变量,只能添加方法。如果需要添加变量,可以通过继承创建子类来实现。
b、Category可以实现原始类的方法,但却会覆盖掉原来的方法,这么做的后果是再也不能访问原来的方法。
c、如果多个Category中如果实现了相同的方法,只有最后一个参与编译的才会有效。