[黑马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;
传统的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
- [黑马IOS自学第十一篇]OC语言基础,SELF关键字,面向对象概念,类学习多态,继承@property等
- [黑马IOS自学第十篇]OC语言基础,面向对象概念,类学习
- [黑马IOS自学第九篇]OC语言基础,面向对象概念,类的创建,OC多文件开发等
- iOS概念入门学习-OC-@property关键字
- 黑马程序员IOS-OC语言-面向对象
- 黑马程序员-iOS学习日记(五)面向对象-self和super关键字
- 黑马程序员---【OC语言】04面向对象之继承与多态
- 黑马程序员——OC语言基础:面向对象三大特性,封装、继承、多态
- 黑马程序员——OC语言基础——面向对象三大特性之继承
- 【黑马程序员】【OC语言】self关键字
- 黑马程序员 OC基础: 面向对象_继承&多态(三)
- OC基础语法<1.3> 入门面向对象语法-self、new、 @property和synthesize
- 黑马-OC语法-self(关键字),“.”语法,声明对象等默认类型
- 黑马程序员——Java基础---面向对象(继承_概述、关键字final、抽象类)(5) 分类: Java学习笔记
- ios开发-OC类方法和self关键字的学习
- 黑马程序员-OC语言基础:面向对象语法 一
- 黑马程序员-OC语言基础:面向对象语法 二
- 黑马程序员-OC语言基础:面向对象语法 三
- 【SSH进阶之路】一步步重构MVC实现Struts框架——从一个简单MVC开始(三)
- 泛型
- HTML5 页面编辑API之Range对象
- Tiny 6410 UART0 输出乱码
- 第三章 UI开发
- [黑马IOS自学第十一篇]OC语言基础,SELF关键字,面向对象概念,类学习多态,继承@property等
- 每日构建系列(1):入门篇
- 这像是在扯皮吗
- ubuntu中安装man手册查看函数原型
- StringBuffer
- 每日构建系列(2):架构篇
- 关于xwindow的一些事
- c++_7: 拷贝构造函数和赋值构造函数
- 以手机app讲解wireshark的简单使用