------Java培训、Android培训、iOS培训、.Net培训 期待与您交流! -------
本篇主要通过一些小案例来讲述OC的一些核心语法,包括点语法、property、构造方法和分类等,本章内容的开发工具是Xcode,不再使用前面的终端来编译和运行程序了。
点语法
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
int _age;
}
- (void)setAge:(int)age;
- (int)age;
@end
Person.m里的内容:
#import "Person.h"
@implementation Person
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
@end
p.age = 10;这一句是调用了_age的set方法
成员变量的作用域
@private 只能在当前类的对象方法中访问(子类不能直接访问,但是内存中是有这个变量的)
@protected 能在当前类和子类的对象方法中直接访问
默认情况是protected
@package 两个类处于同一个框架中,就能直接访问对象的成员变量
声明中的成员变量默认是protected
实现中也是可以定义成员变量,但是成员变量是private的,并且实现中不能定义和@interface中同名的成员变量
不声明直接写实现也是可以的,但是一般不会这样写,有声明有实现程序才会完整
OC中是单继承,一个类只能继承一个父类
@property和@synthesize
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
int _age;
}
@property int age;
@end
实现可以变成
#import "Person.h"
@implementation Person
@synthesize age = _age;
@end
代码一下精简好多,还可以更精简一点,成员变量的定义也可以省略,Xcode可以帮我们自动生成 _age 成员变量。
id
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
id d = [Person new];
Person *d2 = [Person new];
d2.age = 20;
[d setAge:10];
NSLog(@"d = %d,d2 = %d",[d age],d2.age);
}
return 0;
}
构造方法
(1)构造方法的init方法重写
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool
{
Person *p = [Person new];
/*
完整的创建一个可用的对象
1.分配存储空间 +alloc
2.初始化 -init
*/
Person *p1 = [[Person alloc] init];
NSLog(@"%d,p.age = %d",p1.age,p.age);
Student *s1 = [[Student alloc] init];
NSLog(@"年龄是%d,学号是%d",s1.age,s1.no);
Student *d1 = [[Student alloc] init];
d1.age = 20;
NSLog(@"%d",d1.age);
}
return 0;
}
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property int age;
@end
#import "Person.h"
@implementation Person
- (instancetype)init
{
//1.调用父类的init方法并且赋值给self
//返回当前对象:初始化父类中的成员变量,self
//2.判断self不为空,则是初始化成功
if (self = [super init])
{
_age = 10;
}
//3.返回初始化的对象,也就是self
return self;
}
@end
上面就是对Person类的init方法进行重写,在调用了父类的init方法之后,编写自己需要初始化的内容
Student类
#import "Person.h"
@interface Student : Person
@property int no;
@end
#import "Student.h"
@implementation Student
- (instancetype)init
{
if (self = [super init])
{
_no = 1;
}
return self;
}
@end
Student类也进行了重写,在把Person把年龄初始化为10之后,又把学号初始化为1。
2015-04-15 16:56:34.895 构造方法[3630:303] 10,p.age = 10
2015-04-15 16:56:34.897 构造方法[3630:303] 年龄是10,学号是1
2015-04-15 16:56:34.897 构造方法[3630:303] 20
(2)自定义构造方法
1.一定以 - 开头
2.返回 id 类型
3.方法名一般以initWith开头
- (id)initWithName:(NSString *)name AndAge:(int)age
{
if (self = [super init])
{
_name = name;
_age = age;
}
return self;
}
自定义构造方法也是需要调用父类的init方法的
Category(分类)和类的本质
(1)分类
可以给某一个类扩充一些方法,不修改原来类的代码作用
可以在不改变原来类内容的基础上,可以为类增加一些方法
使用注意
1.分类只能扩充方法,不能增加成员变量
2.分类可以访问原来类中声明的成员变量
3.分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法无法使用
4.方法调用的优先级:分类 --> 原来类 --> 父类
(2)类的本质
其实类也是一个对象,Class类型的对象
类对象就是指类
会先把类加载进内存,类只会加载一次
1 Person *p = [[Person alloc] init];
class c = [p class];
2 [Person class];
所有的对象获取的类对象都是同一个
初始化 当第一次使用这个类的时候,就会调用一次+initialize(如果分类中有,只会调用分类中的)
(3)综合应用
#import "Person.h"
@implementation Person
+ (void)load
{
NSLog(@"PERSON-load");
}
+ (void)initialize
{
NSLog(@"person-initialize");
}
@end
Student.m
#import "Student.h"
@implementation Student
+ (void)load
{
NSLog(@"STUDENT-load");
}
+ (void)initialize
{
NSLog(@"student-initialize");
}
@end
Person+test.h(分类,注意分类只能扩充方法,不能扩充成员变量)
#import "Person.h"
@interface Person (test)
@end
test是分类名,实际开发中一般会按功能来命名
#import "Person+test.h"
@implementation Person (test)
+ (void)load
{
NSLog(@"test-load");
}
+ (void)initialize
{
NSLog(@"test-initialize");
}
@end
其实上面的代码就是为所有的类和分类重写了 +load和 +initialize方法
2015-04-15 17:59:15.821 类的本质[4008:303] PERSON-load
2015-04-15 17:59:15.822 类的本质[4008:303] STUDENT-load
2015-04-15 17:59:15.823 类的本质[4008:303] test-load
2015-04-15 17:59:15.823 类的本质[4008:303] test-initialize
2015-04-15 17:59:15.823 类的本质[4008:303] student-initialize
这说明了程序在运行时确实将所有的类和分类加载进来,但是调用+initialize却是使用的时候才会调用,而且如果分类中有该方法的重写的话是不会调用原来类的initialize方法的,本段代码中Person的initialize方法就没有调用,而创建的时Student对象(多态),所有它的方法被调用了description
@property int age;
@property NSString *name;
main.m中有如下代码,那么究竟会打印什么呢?
Person *p = [[Person alloc] init];
p.age = 20;
p.name = @"Jack";
NSLog(@"\n%@",p);//调用description方法
结果是:
2015-04-15 18:11:47.339 description[4137:303]
<Person: 0x100107300>
上面结果打印的时类名和地址@implementation Person
- (NSString *)description
{
NSString *s = [NSString stringWithFormat:@"年龄是%d,姓名是%@",self.age,self.name];
return s;
}
@end
[NSString stringWithFormat:@"年龄是%d,姓名是%@",self.age,self.name];这一句是指按照某种格式创建一个NSString对象
2015-04-15 18:16:27.463 description[4163:303]
年龄是20,姓名是Jack
OK,搞定了!