=====文档变更状态====
2015-12-14:发布
2015-12-15:
1>setter、getter点语法的条件补充用【补1-S】【补1-E】标记开始和结束
2>增加了关于super和self的一些朴素介绍用【补2-S】【补2-E】标记开始和结束
=================
day03_2015-12-14
一、变长参数
1.使用C语言的stdarg.h库
A.va_list类型
B.va_start、va_arg、va_end函数
2.没有结束判断,需要自己在代码中进行,一般通过在参数末尾增加一个与有效参数无关的标志来实现结束判断
3.不仅函数,方法也可以接收变长参数
// 一个例子
#import <Foundation/Foundation.h>
@implementation VarParam:NSObject
+(int)getMax:(int)a,...{
int temp=a;
// 1.定义一个指针用于指向变长参数
va_list vp;
// 2.开始获取变长参数位置
va_start(vp, a);
// 3.获取第一个变长参数的值
int n=va_arg(vp, int);
// 4.循环判断
while (n!=INT_MIN) {// 如果写成while(n)则n为0时结束那么
// 此函数不能读入0
// 比如 int max =[VarParam getMax(-10,-30,0,25)读取会出问题]
if (n>temp) {
temp=n;
}
n=va_arg(vp, int);
}
va_end(vp);
return temp;
}
@end
int getMin(int a,...){
int temp=a;
va_list vp;
va_start(vp, a);
int n=va_arg(vp, int);
while (n!=INT_MAX) {
if (n<temp) {
temp=n;
}
n=va_arg(vp, int);
}
va_end(vp);
return temp;
}
int main_var_param(){
int max=[VarParam getMax:-35,10,0,20,23,12,34,INT_MIN];//-2^31
NSLog(@"max=%d",max);
int min=getMin(10,20,34,-34,-23,-12,INT_MAX);
NSLog(@"min=%d",min);
return 0;
}
//变长参数结束的标志的解决方式:<c的库stdarg.h的缺陷导致要解决判断参数的个数问题>
//1.是通过在参数的末尾放一个标记
// 2.类似于printf用占位符标记参数的个数
// 3.第一个参数用于标记参数的个数
二、封装
1.解决数据的有效性(合法又合理)、读写性
2.成员变量的默认权限:
在接口部分是保护的:@protected
在实现部分是私有的:@private
3.封装步骤
A.成员变量私有化;
B.声明相应的getter和setter
C.给出getter和setter的实现
4.getter:除BOOL类型外,方法名与要封装的成员变量同名,有返回值(与封装的成员变量相同)无参数;BOOL类型使用is开头加上要封装的成员变量名作为方法名
5.setter:使用set开头加上要封装的成员变量名作为方法名,无返回值有参数(类型与要封装的成员变量相同);在setter中通过代码控制数据的有效性
6.如果只提供getter不提供setter,即为只读性
7.BOOL类型:getter方法名使用is开头
8.NSString类型:setter中一般调用参数的copy方法赋值
// person
// YYPerson.h
#import <Foundation/Foundation.h>
@interface YYPerson : NSObject
{
@private
int _age;
char _gender;//M F
NSString* name;
BOOL married;
}
-(int)age;
-(void)setAge:(int)age;
-(char)gender;
-(void)setGender:(char)gender;
-(void)setName:(NSString *)name;
-(NSString *)name;
-(void)setMarried:(BOOL)married;
-(BOOL)isMarried;
@end
// YYPerson.m
#import "YYPerson.h"
@implementation YYPerson
-(int)age{
return _age;
}
-(void)setAge:(int)age{
if (age<0 || age>150) {
_age=20;
}
else{
_age=age;
}
}
-(char)gender{
return _gender;
}
-(void)setGender:(char)gender{
// if (gender=='M' || gender=='F') {
// _gender=gender;
// }
// else{
// _gender='M';
// }
if (gender!='M' && gender!='F') {
_gender='M';
}
else{
_gender=gender;
}
}
// NSString 类型setter要用copy
-(void)setName:(NSString *)name
{
_name = [name copy];
}
-(NSString *)name
{
return _name;
}
// 注意BOOL类型setter、getter方法的写法
// 是想保证_married 必须被赋予NO或YES 值而不是传进来的数// 字 比如传进来10则_married被赋值为YES
// getter方法要以is开头
-(void)setMarried:(BOOL)married
{
if (married == NO)
{
_married = NO;
}
else
{
_married = YES;
}
}
-(BOOL)isMarried
{
return _married;
}
-(void)
@end
// test_person.m
#import "YYPerson.h"
int main(){
XBPerson *per = [[XBPerson alloc] init];
[per setAge:20];
[per setName:@"mike"];
[per setMarried:10];
// 规范的点调用<这里的规范指的是方法名>
NSLog(@"name:%@,married:%d",per.name,per.isMarried);
// 不规范的点调用<这里的不规范指的是方法名aaMarried>
NSLog(@"name:%@,married:%d",per.name,per.aaMarried);
// 综上点的调用,点语法只是告诉编译器我要调用方法,至于调用
//哪个方法由用法指定,系统默认调用的是规范的setter,getter方法
// 点语法还可以访问其它非属性方法即非settter getter方法【补1—S】只能调用不带参数只有返回值的方法【补1-E】
return 0;
}
// 注意
1>NSString 的setter方法要用copy
2>BOOL类型的setter、getter方法的写法
3>点语法的本质
4>当点语法与BOOL类型混在一起时:如下
@property (nonatomic,assign,getter=isMan) int man;
则在main方法使用的时候,即可以用:
a> 对象名.man 和对象名.isMan
b> [对象名 isMan]不能用[对象名 man],
综上:<点语法调用方法比普通方法调用多一个功能【补1-S】但这种功能只是限制在能调用不带参数的非getter setter方法【补1-E】>
通过点语法可以访问改名前的方法而通过[对象 方法名]则不能
三、封装之self关键字
1.区别同名的成员变量和局部变量(包括参数):仅在对象方法中可以使用
在对象方法中,如果成员变量已经规范封装,可以使用self.成员变量的形式访问
在对象方法中如果需要访问其它对象方法,可以使用[self 其它对象方法]的形式访问
2.调用类中其它方法:对象方法中调用其它对象方法,类方法中调用其它的类方法
在类方法中,代表当前类,可以使用[self 其它类方法名]的形式访问类方法,但无法直接访问
其它对象方法、成员变量
// YYPersonPro
// YYPersonPro.h
#import <Foundation/Foundation.h>
@interface YYPersonPro : NSObject
{
//默认是保护权限,子类中可以直接访问
int prot;
@private
int age;
char _gender;//M F
NSString* _name;
}
-(int)age;
-(void)setAge:(int)age;
-(char)gender;
-(void)setGender:(char)gender;
-(NSString*)name;
-(void)setName:(NSString*)name;
+(void)classMethod1;
+(void)classMethod2;
-(void)say;
-(void)eat:(NSString*)food;
@end
// YYPersonPro.m
#import "YYPersonPro.h"
@implementation YYPersonPro
+(void)classMethod1{
NSLog(@"class method 1");
[self classMethod2];
}
+(void)classMethod2{
NSLog(@"class method 2");
//类方法中不能使用self调用对象方法
// [self setAge:10];
}
-(NSString *)name{
return _name;
}
-(void)setName:(NSString *)name{
_name=[name copy];
// [self setAge:10];
//对象方法中不能使用self调用类方法
// [self classMethod1];
}
-(int)age{
return age;
}
-(void)setAge:(int)age{
if (age<0 || age>150) {
self->age=20;
}
else{
self->age=age;
}
}
-(char)gender{
return _gender;
}
-(void)setGender:(char)gender{
if (gender!='M' && gender!='F') {
_gender='M';
}
else{
_gender=gender;
}
}
-(void)say{
NSLog(@"I am %@,age is %d,gender is %c.",_name,age,_gender);
}
-(void)eat:(NSString *)food{
NSLog(@"Person %@ is eatting %@.",_name,food);
}
@end
// test1.m
#import "YYPersonPro.h"
int main_pp(){
YYPersonPro* per=[YYPersonPro new];
[per setAge:10];
NSLog(@"age:%d",[per age]);//0
return 0;
}
四、继承inheritance
1.继承的语法:@interface 子类名:父类名
2.继承的作用:减少代码冗余,子类可以拥有父类的所有,还可以增加新的内容
3.注意:继承要符合“is a”关系,不能仅仅为了减少代码冗余而去继承
4.访问权限
@private @protected @public
本类中 可以 可以 可以
子类中 不可以 可以 可以
类外 不可以 不可以 可以
另外还有@package(软件包)权限
5.关于同名:
A.子类中不允许出现与父类同名的成员变量
B.子类中可以有与父类同名的方法,在调用时通过super和self区别;如果方法与父类同名,可以省略声明部分
【补2-S】
关于super和self特点的唐僧解释1
super关键字:用于访问父类中与子类同名的方法;如果子类中有与父类同名的方法,使用self和super效果不同;如果子类中没有与父类同名的方法,使用self和super效果相同;
关于super和self特点的唐僧解释2
如果子类中有与父类同名的方法(即重写)则在一个方法中[self 方法名]和[super 方法名(重写后)]调用的是不同的方法(前者调用重写前后者调用重写后),但是如果没有重写方法则 [super 方法名]和[self 方法名]调用的是同一个方法,这种现象的原因在于:用户调用方法时,系统始终是从当前类里找方法,如果没找到然后再到父类中找
【补2-E】
// YYTeacher
// YYTeacher.h
#import "YYPersonPro.h"
@interface YYTeacher : YYPersonPro
{
@private
//子类中不允许出现与父类同名的成员变量
//int age;
int _salary;
NSString* _course;
}
-(int)salary;
-(NSString*)course;
-(void)setSalary:(int)salary;
-(void)setCourse:(NSString*)course;
-(void)teacherSay;
//子类中可以有与父类同名的方法,在调用时通过super和self区别
//如果方法与父类同名,可以省略声明部分
//-(void)say;
@end
// YYTeacher.m
#import "YYTeacher.h"
@implementation YYTeacher
-(int)salary{
return _salary;
}
-(NSString *)course{
return _course;
}
-(void)setSalary:(int)salary{
if (salary<0) {
_salary=0;
}
else{
_salary=salary;
}
}
-(void)setCourse:(NSString *)course{
_course=[course copy];
}
-(void)say{
NSLog(@"YYTeacher say!");
}
-(void)teacherSay{
// [super say];
NSLog(@"I am teacher %@,age is %d,gender is %c,teaching %@,my salary is %d.",[super name],[super age],[super gender],self->_course,self->_salary);
}
-(void)eat:(NSString *)food{
NSLog(@"Teacher %@ is eatting %@",[self name],food);
}
@end
// test_teacher.m
#import "YYTeacher.h"
int main_inher(){
YYTeacher* tom=[YYTeacher new];
[tom setName:@"Tom"];
[tom setAge:40];
[tom setGender:'f'];
[tom setSalary:33300];
[tom setCourse:@"iOS"];
NSLog(@"gender:%c",[tom gender]);//M
NSLog(@"salary:%d",[tom salary]);//0
[tom teacherSay];
[tom say];
return 0;
}
=================EOF===============