[黑马IOS自学第十一篇]OC语言基础,SELF关键字,面向对象概念,类学习多态,继承@property等

来源:互联网 发布:南风知我意2全文 编辑:程序博客网 时间:2024/05/05 22:12


 

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];即调用类方法

typedefstructobjc_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;

传统的getset方法

#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文件中实现setget方法的实现

#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重写getset方法

数据校验

#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

0 0
原创粉丝点击