self在对象方法中使用
self类似其他语言的指针
用在对象方法中使用时,相当于调用当前方法的那个对象
<span style="font-size:14px;">#import"Person.h"
@implementation Person
-(void)run{
NSLog(@"人在跑步");
}
-(void)eat:(NSString*)foodName{
NSLog(@"人在吃饭:%@",foodName);
[selfrun];
}
@end</span>
3.self在类方法中使用其指代的是当前类
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p = [Personnew];
NSLog(@"打印地址p=%p",p);//对象的地址
NSLog(@"打印地址Person=%p",[pclass]);//返回当前类的地址
[Personrun];
//类中的self一定不指代当前的对象P
/*
2015-12-09 10:52:09.840 self用在类方法中[21391:2580702]打印地址p=0x1003085f0
2015-12-09 10:54:03.142 self用在类方法中[21408:2582305]打印地址Person=0x1000011f8
2015-12-09 10:52:09.842 self用在类方法中[21391:2580702]+run
2015-12-09 10:52:09.844 self用在类方法中[21391:2580702]self = 0x1000011f8
*/
}
return 0;
}
#import"Person.h"
@implementation Person
+(void)run{
NSLog(@"+run");
NSLog(@"self = %p",self);
[selftest];//实用类调用类方法
//[selfeat];//self是类,不能调用对象方法
}
+(void)test{
NSLog(@"+test");
}
-(void)eat{
NSLog(@"-eat");
}
@end
2).self修饰实例变量
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p =[Personnew];
[p setSpeed:80];
NSLog(@"Speed:%d",[p speed]);
}
return 0;
}
#import<Foundation/Foundation.h>
@interface Person :NSObject
{
int speed ;
}
-(void)setSpeed:(int)speed;
-(int)speed;
@end
#import"Person.h"
@implementation Person
-(void)setSpeed:(int)speed{
//_speed =speed;//80
//speed=speed;//0
//两个局部变量
//加上self后表示访问的就是类的实例变量
self->speed =speed;//如果实例变量名和局部变量名成名的情况
}
-(int)speed{
return speed;
}
@end
4.self试用总结
5.OC中继承与派生
基类(父类)
派生类(满足父类的一些特性)
继承可以减少代码,重复使用
基类和派生类之间的关系
派生类方法属性==基类的方法属性+派生类自己新增的方法和属性
1.基类的私有属性能被继承,不能被使用
2.OC是单继承,一个类只能继承一个父类
3.继承的合理性,不能让人继承交通工具的类
4.支持多层继承,动物-->狗-->军犬(大黄狗),
5.如果方法NSObject也没有,就报错了
6.不能定义和父类重名的成员变量
重点:方法的重写
实例变量作用域
@public ---->任意程序集
@protected---->同一类和派生类(默认情况下)
@private------>同一类
#import<Foundation/Foundation.h>
@interface Person :NSObject
{
@public //任何类中都可以使用
NSString *_name;
@protected//当前类和子类中使用
float _weight;
@private //当前类方法中可以使用
int _age;
}
-(void)run;
@end
#import"Dog.h"
@implementation Dog
-(void)run{
NSLog(@"public age:%d",_age);
NSLog(@"protected_legNum :%d",_legNum);
//NSLog(@"priveat_weight :%d",_weight);
//子类可以继承父类的所有实例变量和方法,但是private修饰的变量无法访问
}
@end
6.私有变量的知识点
.m文件中定义的变量,子类的.m文件中不能使用 ,而父类.h中定义的变量是可以调用的
oc的私有方法(对外隐藏)
在.h没有被申明,而在.m中实现,的方法成为私有方法
私有方法不能被子类继承
test方法没有在Person.h声明,无法被student类继承
在.m文件中通过self调用test方法,或者是通过在person对象创建对象调用test方法(容易搞混,不推荐使用)
7.Description方法介绍及重写
#import<Foundation/Foundation.h>
#import"Dog.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Dog *d = [Dognew];
[d run];
[d setAge:10];
NSLog(@"查看对象地址 = %p",d);
NSLog(@"对象实例变量的值 = %d",[d age]);
//打印Dog创建的对象
NSLog(@"%@",d);
//调用了对象的description方法
NSLog(@"%@",[dclass]);
//调用类方法的description
}
return 0;
}
//对象中如果没有description方法,则调用父类的
#import"Dog.h"
@implementation Dog
-(void)run{
NSLog(@"狗狗正在跑步");
}
-(void)setAge:(int)age{
_age = age ;
}
-(int)age{
return _age;
}
-(NSString *)description{
return@"重写description方法";
}
+(NSString *)description{
//类方法不能访问实例变量
//return[NSString stringWithFormat:@"年龄:",_age];
return@"类方法中description";
}
@end
2).Description陷阱
8.多态
某一类实物的多种形态
程序中不同对象以自己的方式响应父类同名的方法称为多态
表现:
父类的指针指向子类对象
#import<Foundation/Foundation.h>
#import"Dog.h"
#import"Animal.h"
#import"Cat.h"
#import"BigDog.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Animal *a1 = [Animal new];
[a1 run];
//[(Dog*)a1 eat];
//强制转换,能骗过编译器,但在运行的时候会报错
/*
*** First throw call stack:
(
0 CoreFoundation 0x00007fff89e7de32__exceptionPreprocess + 178
1 libobjc.A.dylib 0x00007fff899ae4faobjc_exception_throw + 48
2 CoreFoundation 0x00007fff89ee734d-[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00007fff89dee661 ___forwarding___ +1009
4 CoreFoundation 0x00007fff89dee1e8_CF_forwarding_prep_0 + 120
6 libdyld.dylib 0x00007fff852885ad start + 1
)
libc++abi.dylib: terminating with uncaught exception oftype NSException
warning: could not load any Objective-C class informationfrom the dyld shared cache. This will significantly reduce the quality of typeinformation available.
*/
Animal *a2 = [Dog new];
[a2 run];
//[a2eat];
//因为Animal中没有此eat方法,所以编译的时候会报错
//eat是Dog定义的方法,eat方法在Animal中没有
[(Dog*)a2eat];
//强制转换之后可以调用Dog类中的eat方法
Animal *a3 = [Cat new];
[a3 run];
Dog *d4 = [BigDognew];
[d4 run];
Animal *a5 = [BigDog new];
[a5 run];
}
return 0;
}
9.类的本质
类类型变量(实例对象)
Person是一个对象(类对象),Class类型
类对象的获取方法
#import<Foundation/Foundation.h>
#import"Dog.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Dog *d = [Dognew];
[d test];
[Dogtest];
Dog *d1 = [Dognew];
// 类对象的获取方法
//类对象属于Class类型
//1.通过实例对象来获取类对象
Class c1 = [d class];
Class c2 = [d1class];
NSLog(@"%p",c1);
NSLog(@"%p",c2);
//2.通过类名来获取类对象
Class c3 = [Dogclass];
NSLog(@"%p",c3);
}
return 0;
}
Class本身就是指针,所以Class c3 = [Dogclass];c3不需要加*
C3相当于 ---类名
[c3test];即调用类方法
typedefstruct objc_class *Class;
类对象的存储细节
(原类对象)
int main(intargc,const char* argv[]) {
@autoreleasepool {
//typedefstruct objc_selector *SEL;
SEL s1 = @selector(test);
//手动的将test方法包装成SEL类型数据
Person *p =[Personnew];
//响应方法
[p performSelector:s1];
}
return 0;
传统的get和set方法
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
//传统的get和set方法
Person *p = [Personnew];
[p setAge:18];
[psetName:@"刘宇"];
NSLog(@"姓名:%@,年龄:%d", [p name], [page]);
}
return 0;
}
点语法介绍和使用
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p = [Personnew];
p.age = 100 ;
p.name =@"刘晓晓";
//编译器看到点语法后,自动替换成 [psetAge:18]
//而下方的p.age调用的get方法
int age = p.age;
NSString *name = p.name;
//p.age 并不是直接访问实例变量
NSLog(@"姓名:%@,年龄:%d", name, age);
NSLog(@"姓名:%@,年龄:%d", p.name, p.age);
//点语法:xcode的特性,xcode帮我们做代码替换
}
return 0;
}
#import"Person.h"
@implementation Person
-(void)setAge:(int)age{
_age =age ;
}
-(int)age{
return _age;
}
-(void)setName:(NSString*)name{
_name = name ;
}
-(NSString*)name{
return _name;
}
@end
@property数据类型后跟的是方法名 自动生成get/set方法
父类的@property
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p = [Personnew];
p.age = 18 ;
p.name =@"zhenzhenPo";
//相当于
//[psetAge:10];
//[psetName:@"oi"];
NSLog(@"姓名:%@,年龄:%d",p.name,p.age);
}
return 0;
}
#import<Foundation/Foundation.h>
@interface Person :NSObject
{
}
@propertyint age ;
//声明和实现了_age,_name的get和set方法
生成的 _age _name都是私有(相对)变量
//成员变量不能够被子类继承,子类可以重写父类的setget方法
@propertyNSString* name;
@end
//Xcode4.4之后可以不跟@systhesize实现代码不写也能成功调用方法
#import"Person.h"
@implementation Person
-(void)setName:(NSString*)name{
self->_name= name;
}
-(void)setAge:(int)age{
self->_age =age;
}
-(int)age{
return _age;
}
-(NSString *)name{
return _name;
}
@end
@synthesize关键字介绍和使用
在.m文件中实现set和get方法的实现
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p = [Personnew];
p.age = 10 ;
p.name =@"synthesize name";
NSLog(@"姓名 :%@",p.name);
NSLog(@"年龄 :%d",p.age);
[p test];
}
return 0;
}
#import<Foundation/Foundation.h>
@interface Person :NSObject{
int _age;
NSString * _name;
}
-(void)test;
@propertyint age ;
@propertyNSString *name;
@end
#import"Person.h"
@implementation Person
@synthesize age;
@synthesize name;
-(void)test{
NSLog(@"\n_age :%d,_name :%@",_age,_name);
NSLog(@"\nage :%d ,name:%@",age,name);
//理解为在生成的setAge方法中 self->age = age ;
}
@end
@synthesize指定实例变量赋值
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p = [Personnew];
p.age = 10 ;
p.weight =190;
p.name =@"synthesize name";
NSLog(@"姓名 :%@",p.name);
NSLog(@"年龄 :%d",p.age);
NSLog(@"体重 :%d",p.weight);
[p test];
}
return 0;
}
@interface Person :NSObject{
int _age;
NSString * _name;
int _weight;
int age;
NSString * name;
int weight;
}
-(void)test;
@propertyintage ,weight ;
@propertyNSString *name;
@end
#import"Person.h"
@implementation Person
//@synthesizeage;
@synthesize name; /理解为跟着的方法名
//如果两个实例变量的类型一致,如都是int类型
//直接操作定义的成员变量 _weight ,_age
@synthesize weight =_weight,age= _age;
//默认操作的就是_weight ,_age
-(void)test{
NSLog(@"\n_age :%d,_weight :%d",_age,_weight);
NSLog(@"\n age :%d,weight :%d",age,weight);
//理解为在生成的setAge方法中 self->age = age ;
}
@end
此时的=_weight , =_age就有值了
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p = [Personnew];
p.age =10;
p.name =@"sdsd";
[p test];
}
return 0;
}
#import<Foundation/Foundation.h>
@interface Person :NSObject
{
/*
int _age ;
NSString * _name ;
int age ;
NSString * name ;
*/
}
//Xcode 4.4之后可以只是用@property而不使用@synthesize
//声明和实现了下划线_age,_name get set方法
//操作的是带下划线的变量
//没有下划线变量自动生成
@propertyint age ;
@propertyNSString* name;
-(void)test;
@end
#import"Person.h"
@implementation Person
-(void)test{
NSLog(@"_name =%@,_age=%d",_name,_age);
NSLog(@"\n name =%@,age=%d",name,age);
}
@end
@property重写get和set方法
数据校验
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p = [Personnew];
p.age =-18;
p.name =@"sdsd";
NSLog(@"姓名:%@,年龄:%d",p.name,p.age);
}
return 0;
}
#import<Foundation/Foundation.h>
@interface Person :NSObject
{
}
@propertyint age ;
@propertyNSString *name;
@end
#import"Person.h"
//get和 set方法只能重写覆盖其中一个,
用@synthesize可以重写两个,编译器认为两个都重写不需要使用@property
@implementation Person
-(void)setAge:(int)age{
if(age>0)
_age =age ;
else
_age = 0;
}
-(void)setName:(NSString*)name {
if ([name length]>0){
_name = name;
}
else {
NSLog(@"name不能为空");
}
}
@end
动态类型&静态类型
即运行时再决定对象的类型。这类动态特性在日常应用中非常常见,简单说就是id类型。id类型即通用的对象类,任何对象都可以被id指针所指,而在实际使用中,往往使用introspection来确定该对象的实际所属类:
动态类型:
Animal*an = [Dog new];
静态类型:
Person *p =[Person new ];
NSObject访问子类对象的方法
#import<Foundation/Foundation.h>
#import"Animal.h"
#import"Dog.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
//因NSObject中没有run方法,所以要强制转换一下
NSObject *obj1 = [Animal new];
[(Animal*)obj1run];
NSObject *obj = [Dog new];
[(Dog*)objrun];
//动态绑定就是运行的时候去判断
id obj2 = [Dognew];
[obj2 run];
Dog *dg = [Dognew];
id obj3 = dg;
[obj3 run];
//NSObject 和 id可以指向任何对象
//id不需要强制类型转换
//编译器不检查id的类型,认为是动态类型,运行时才报错
}
return 0;
}
动态检测,在运行之前,检测到方法是否运行。
1.判断类型,判断实力对象是否是这个类或者这个对象的子类的实例
#import<Foundation/Foundation.h>
#import"Animal.h"
#import"Dog.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Animal *ani = [Animal new ];
// ani 是Animal类的实力对象
//isKindOfClass 对象和类关系
BOOL isInstance = [ani isKindOfClass:[Animalclass]];
NSLog(@"%d",isInstance);//1
Dog *dog = [Dognew];
isInstance = [ dogisKindOfClass:[Animalclass]];
NSLog(@"%d",isInstance);//1
//2.isMemberOfClass 判断对象是否是指定类的实力对象(不算子类),
//对象和类关系
isInstance = [dogisMemberOfClass:[Animalclass]];
NSLog(@"%d",isInstance);//0
isInstance = [aniisMemberOfClass:[Animalclass]];
NSLog(@"%d",isInstance);//1
//3.判断这个类是否是其子类(类和类的关系)
BOOL isSubClass = [Dog isSubclassOfClass:[Animal class]];
NSLog(@"%d",isSubClass);//1
//1表示DOg类继承自 Animal类
isSubClass = [[dogclass] isSubclassOfClass:[Animalclass]];
NSLog(@"%d",isSubClass);//1
}
return 0;
}
#import<Foundation/Foundation.h>
#import"Dog.h"
int main(int argc,const char * argv[]) {
@autoreleasepool {
Animal *ani = [Animalnew];
//[(Dog*)ani eat]; ani对象没有eat方法
SEL s1 =@selector(eat);
//1,判断实例子对象能否响应指定的方法
BOOL isRespMethods = [anirespondsToSelector:s1];
NSLog(@"%d",isRespMethods);//0
//表示 ani中没有 eat方法
//2.判断类能否响应(调用)指定的方法
isRespMethods = [DoginstancesRespondToSelector:s1];
NSLog(@"%d",isRespMethods);//1
//继承关系有run方法
isRespMethods = [DoginstancesRespondToSelector:@selector(run)];
NSLog(@"%d",isRespMethods);//1
}
return 0;
}
判断对象能否响应指定的方法
#import<Foundation/Foundation.h>
#import"Dog.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Animal *ani = [Animal new];
SEL s1 = @selector(eat);
if([ani respondsToSelector:s1]){
//performSelector响应无参的方法
[ani performSelector:s1];
}
else{
NSLog(@"该对象不能执行eat方法");
}
SEL s2 = @selector(eat:);
if([ani respondsToSelector:s2]){
//performSelector响应一个参数的方法
[aniperformSelector:s2withObject:@"一块沾有糖心的巧克力"];
}
else{
NSLog(@"该对象不能执行eat方法");
}
SEL s3 = @selector(eat:andfooName:);
if([ani respondsToSelector:s3]){
//performSelector响应有两个参数的方法
[aniperformSelector:s3withObject:@"贵宾犬"
withObject:@"一块沾有糖心的巧克力"];
}
else{
NSLog(@"该对象不能执行eat:方法");
}
}
return 0;
}
构造方法,
用来初始化值
#import<Foundation/Foundation.h>
#import"Person.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p1 = [Person new];
//alloc
//init 初始化对象方法,OC给对象初始化的方法
//返回地址
Person *p2 = [[Person alloc] init ] ;
//Person alloc 的时候内存已经清 0
}
return 0;
}
重写构造方法
super使用
#import<Foundation/Foundation.h>
#import"Dog.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Dog* dog = [Dognew];
[dog run];
//先执行子类的run方法,没有则调用父类的run.....
//需求调用父类的run方法
}
return 0;
}
#import"Dog.h"
@implementation Dog
-(void)run{
[superrun];//super表示父类对象表示调用父类的run方法
NSLog(@"汪星人在跑");
}
@end
#import<Foundation/Foundation.h>
#import"Soldier.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Soldier *sd1 = [Soldier new];
//给士兵一杆枪
for (inti = 0 ; i <4 ; i++) {
[sd1 fire];
}
NSLog(@"\n");
Soldier *sd2 = [Soldier new];
for (inti = 0 ; i <4 ; i++) {
[sd2 fire];
}
}
return 0;
}
#import<Foundation/Foundation.h>
#import"Gun.h"
@interface Soldier :NSObject
{
Gun *_gun ;
}
@propertyGun *gun;
-(void)fire;
@end
#import"Soldier.h"
@implementation Soldier
-(instancetype)init{
//没创建一个士兵分配一把枪
if (self = [superinit]) {
Gun *gun = [Gunnew];
gun.bulletCount = 3 ;
_gun = gun;
}
return self;
}
-(void)fire{
[_gunshoot];
}
@end
#import<Foundation/Foundation.h>
@interface Gun :NSObject{
}
@propertyintbulletCount ;
-(void)shoot;
@end
#import"Gun.h"
@implementation Gun
-(instancetype)init{
if (self = [superinit]) {
_bulletCount =3 ;
}
return self;
}
-(void)shoot{
_bulletCount -- ;
if(_bulletCount > 0 )
NSLog(@"枪在射击,PPPPPPPP,剩余子弹:%d",_bulletCount);
else
NSLog(@"子弹剩余0,请上子弹");
}
@end
自定义构造方法:
一定是对象方法,-号开头
返回值一定是id类型
方法名一般以initwith开头
#import<Foundation/Foundation.h>
#import"Person.h"
#import"Student.h"
int main(intargc,const char* argv[]) {
@autoreleasepool {
Person *p = [Personnew ];
NSLog(@"%@,%d",p.name,p.age);
//用指定的值初始化
Person *p1 =[[Personalloc ]initWithName:@"张三"andAge:19];
NSLog(@"%@,%d",p1.name,p1.age);
Person *p2 =[[Personalloc ]initWithName:@"s2三"andAge:29];
NSLog(@"%@,%d",p2.name,p2.age);
Student *s2 =[[Studentalloc ]initWithName:@"冰冰"andAge:(15)andSno:(10)];
NSLog(@"%@,%d,%d",s2.name,s2.age,s2.sno);
}
return 0;
}
#import<Foundation/Foundation.h>
@interface Person :NSObject
{
}
@propertyint age;
@propertyNSString* name;
//要声明initwithxxx方法
-(instancetype)initWithName:(NSString*)name andAge:(int)age;
@end
#import"Person.h"
@implementation Person
-(instancetype)initWithName:(NSString*)name andAge:(int)age{
if (self = [superinit]) {
_name = name;
_age = age;
}
return self;
}
-(instancetype)init{
if (self = [superinit]) {
_name =@"凤姐";
}
return self;
}
@end
#import"Person.h"
@interface Student :Person
@propertyint sno;
-(instancetype)initWithName:(NSString*)name andAge:(int)ageandSno:(int)sno;
@end
#import"Student.h"
@implementation Student
-(instancetype)initWithName:(NSString*)name andAge:(int)ageandSno:(int)sno{
//因为 _name _age私有的
if (self = [superinitWithName:nameandAge:age]) {
_sno = sno;
}
return self;
}
@end