oc语言学习之基础知识点介绍(四):方法的重写、多态以及self、super的介绍

时间:2022-08-26 15:59:47

一、方法重写

/*
重写:当子类继承了父类的方法时,如果觉得父类的方法不适合,那么可以对这个方法进行重新实现,那么这个就重写。 注意:也就是说,一定只能发生在父类和子类关系中。 然后是子类重新实现父类的方法,绝对不是再写一个自己类的方法。 代码中原话叫:子类重写父类方法。 因为父类定义的方法不一定适用于子类。 注意:如果有重写,那么调用的是自己重写后的方法,如果没有重写,那么就调用的是父类的方法。 所以我们方法有一个执行的过程:
1.先去自己类里面找这个方法,如果找到就执行。
2.如果没找到,就去父类中找,如果找到就执行。
3.如果还是没找到,就去父类的父类中找,如果找到就执行。
4.如果没找到继续往上找,直到直到根类(NSObject)还没找到的话,就报错! 注意:子类可以重写父类的方法,但是,不能定义跟父类同名的成员变量 */ #import <Foundation/Foundation.h> //框架,是一个核心基础框架,里面提供了很多OC的基础语法类库,左边代表框架,右边代表这个框架里的头文件。
/*例如:在Animal类中,有一个Cry方法,里面打印出 在叫。然而对于不同的动物来说,都有着不同的叫声,狗是 汪汪汪,猫是 喵喵喵等等,所以Animal类中的Cry方法就不通用了,这个时候 我们需要在重写这个方法。
*/ /*动物类开始*/
@interface Animal: NSObject{
@public
NSString * _name;
//......
} -(void) Cry;
@end @implementation Animal{
-(void) Cry{
NSLog(@"动物在叫。");
}
}
@end /*动物类结束*/ /*猫类开始*/
@interface Cat: Animal{
NSString * _name;
//......
} -(void) Cry; -(void)setName:(NSString *)name; -(NSString *)name; @end @implementation Cat{ -(void)setName:(NSString *) name{
if([name isEqualTo:@"你麻痹"]){
_name = @"无名";
}else{
//给属性赋值为你传进来的参数
_name = name;
}
} -(NSString *)name{
//返回这个属性
return _name;
} -(void) Cry{
NSLog(@"小猫在喵喵喵的叫。");
} }
@end
/*猫类结束*/
/*类似于猫类,可以写出狗类、猪类等*/

二、self和super关键字

/*
之前说过,类方法可以调用另一个类方法,语法就是 [类名 方法名];
那么问题来了,对象方法怎么调用另外一个对象方法?? self:
用途:
1.可以在对象方法里面调用另外一个对象方法。
[self 方法名]; 2.当方法内局部变量和成员变量同名时,用self关键字可以显示的调用成员变量。
语法:self->成员变量名; 之前调用对象方法语法:[对象 方法名];
调用对象属性: 对象->成员变量; 当使用self的时候,self代表谁呢?
答案:
谁调用这个方法,这个方法里的self就是谁!!!
例:现有Person类和Student类,里面都有sayHi和classTest1方法。
[p sayHi];//那么此时sayHi方法里的self就是p对象
[p2 sayHi];//那么此时sayHi方法里的self就是p2对象
[Person classTest1];//那么此时classTest1方法里的self就是Person类
[Student classTest1];//那么此时classTest1方法里的self就是Student类 super:可以显示的调用父类中的方法。
应用场景:当子类改写父类的时候,其实父类的方法功能还是需要用的,只不过又多增加一些特有的操作,那么就可以在改写的时候先用super关键字调用一下父类的原方法,然后再写需要添加的代码。 super其实不代表谁,就是一个关键字,能够方便的让你调用父类的东西而已。
*/
//实例我就 简写了
//Person类
@interface Person:NSObject{ }
-(void) sayHi;
-(void) Test1;
@end
@implementation Person{
-(void) sayHi{
NSLog(@"Person哈哈哈");
}
-(void) Test1{
[self sayHi];
NSLog(@"Person测试");
}
}
@end //Student类
@interface Student:Preson{ }
-(void) sayHi;
-(void) Test1;
-(void) Test2;
@end
@implementation Person{
-(void) sayHi{
NSLog(@"Student哈哈哈");
}
-(void) Test1{
[self sayHi];
NSLog(@"Student测试");
}
-(void) Test1{
[supersayHi];
NSLog(@"Student测试");
}
}
@end #import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
Person p =[Person new];
[p Test1];//Person哈哈哈 Person测试 Student stu =[Studentnew];
[stu Test1];//Student 哈哈哈 Student 测试 [stu Test2];//Person哈哈哈 Student 测试
}
return ;
}

还有一种情况,请看代码

//Person类
@interface Person:NSObject{ }
-(void) Test2;
+(void) Test3;
@end
@implementation Person{
-(void) Test2{
NSLog(@"self=%@",self);
}
+(void) Test3{
NSLog(@"self=%@",self);
}
}
@end //Student类
@interface Student:Preson{ }
-(void) StuTest2;
+(void) StuTest3;
@end
@implementation Person{
-(void) StuTest2{
[super Test2];
NSLog(@"Student测试");
}
+(void) StuTest3{
[super Test3];
NSLog(@"Student测试");
}
}
@end #import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
//Student stu =[Studentnew];
//[stu StuTest2];//打印出Student类
[Student StuTest3];//打印出Student类
}
return ;
}

三、访问修饰符的介绍和用法

/*
@public:所有地方都能访问(注意:是无论哪个地方) @protected(默认): 本类以及子类、子类的子类、子类的子类的子类………………都可以访问 @private:私有的。只能在本类中访问 @package(不会用):介于@public和@private之间的。只能在当前框架中使用,简单来就说就是只能在当前的项目里面用 注意:哪怕是@private的,子类也可以继承到,只是不能用!(不够严谨,以后学到KVC,@private的也可以用) 注意:访问修饰符的修饰范围只能是它定义的位置到下一个访问修饰符 注意:访问修饰符不能修饰方法 “私有”成员变量:
把成员变量,写在@implementation 类名后面的大括号里面。
这种做法可以让子类根本都看不到这个私有成员变量,但是却也继承了,其实只是欺骗了编译器,编译器以为没有,达到“私有”目的。 “私有”方法同上,子类可以继承到,但是不可以直接用。
*/
//实例:
//写在这里就可以做到私有且子类不可见
@implementation Person{
int _age;
}

四、多态

/*

多态:同一种行为,不同的实现
代码中实现多态的步骤:
1.要有继承关系
2.子类重写父类方法
3.用父类类型的指针指向子类的对象
4.然后调用方法
*/
//例如:
//动物类中的动物叫的方法
-(void) AnimalShout(){
NSLog(@"叫叫叫");
}
//猫
-(void) CatShout(){
NSLog(@"喵喵喵");
}
//狗
-(void) DogShout(){
NSLog(@"汪汪汪");
} //调用
Animal ani = [Catnew];
[ani CatShout];//猫叫
ani = [Dog new];
[ani DogShout];//狗叫

五、类的本质和SEL类型

/*
类也是存在内存里面的,存在全局区,对象存在堆区。
类既然存在内存里面,它是以什么类型存的呢???
因为我们说要把数据存在内存里面,都要有相应的数据类型 。
10;用int类型来存。
10.3f; 用float类型来存。
它用的是类类型来存的。类类型就是Class。
Class是一个像int float等等一样的类型。
获得这个类类型的数据:
1.[类名 class] 可以得到
2.[对象 class] 也可以得到
作用:
1. new一个对象
2. 调用类方法 注意:大写的Class是类型 小写的class是方法
类的本质是结构体,类其实也是一个对象,是类类型对象(Class对象); */ #import <Foundation/Foundation.h>
@interface Person : NSObject{ @public
int _age;
} -(void)sayHi; +(void)test; @end @implementation Person -(void)sayHi{
NSLog(@"hello");
} +(void)test{
NSLog(@"类方法调用");
} @end int main(int argc, const char * argv[]) {
@autoreleasepool {
//Person *p = [Person new]; //此时就得到了Person存在全局区的类数据,所以也就是说现在cp就是我们的Person类
Class cp = [Person class]; Person *p = [Person new];//此时p是Person对象 Class cp2 = [p class];//调用对象class方法 NSLog(@"%p",cp);
NSLog(@"%p",cp2); Person *p2 = [cp2 new]; [p2 sayHi]; // NSLog(@"%p",[p valueForKey:@"isa"]); //Class cp相当于写了一个objc_class *cp //怎么用呢???
//平时类可以创建对象,那么我们可不可以用我们刚刚拿到的Class类型的数据来创建对象呢??
/*
Person *p = [cp new]; //等于 Person *p = [Person new]; p->_age = 20; [p sayHi]; Person *p2 = [Person new]; p2->_age = 20; [p2 sayHi];
*/ // [Person test];
// [cp test]; }
return ;
}

上面简单的介绍了类的本质,还有一个SEL类型,请看下面:

/*
方法也是要存储。
方法的类型:
SEL类型 其实类里面(Class对象)里面没有存方法的实现,而是存了一个方法的地址,这个地址就是SEL类型。
方法的实现存哪去了??方法的本质是函数,存在代码区。
我们每次调用方法,其实是把方法包装成了SEL类型,然后去类类型的对象找到它所存的方法列表,进行比对,如果比对成功,则执行,如果所有的列表(包括父类,直到NSObject)都比对完,还没有相等的就报错。
那么我们自己怎么获得方法的SEL类型?
通过
@selector(方法名); 这个就可以得到SEL类型
*/ #import <Foundation/Foundation.h> @interface Person : NSObject -(void)sayHi; +(void)clsTest; @end @implementation Person -(void)sayHi{ NSLog(@"哈哈哈哈哈");
} +(void)clsTest{ NSLog(@"我是类方法");
} @end int main(int argc, const char * argv[]) {
@autoreleasepool { //怎么用SEL类型调用方法????
//因为我们包装的是对象方法,所以先要有对象 Person *p = [Person new]; // //得到SEL类型了
// SEL funcSay = @selector(sayHi);
//
// [p performSelector:funcSay]; [p performSelector:@selector(sayHi)]; //这句和上面两句一样 //类方法应用类名调用
[Person performSelector:@selector(clsTest)];
}
return ;
}

oc语言学习之基础知识点介绍(四):方法的重写、多态以及self、super的介绍的更多相关文章

  1. oc语言学习之基础知识点介绍(二):类和对象的进一步介绍

    一.类.对象在内存中的存储 /* 内存分区: 栈:局部变量 堆:程序员自己写代码申请开辟的 程序员自己维护,编译器现在帮我们自动优化了,它在合适的给我们加上了释放空间的语句,所以我们现在写的对象不会造 ...

  2. oc语言学习之基础知识点介绍(五):OC进阶

    一.点语法介绍 /* 以前封装后,要给属性赋值,必须调用方法 这样做,有两个缺点: 1.代码量多,调用方法要写的东西多. 2.看起来并不像是给属性赋值,也不像取值. 我们用点语法就可以更好的解决! 点 ...

  3. oc语言学习之基础知识点介绍(一):OC介绍

      一.第一个OC程序 #import <Foundation/Foundation.h> //导入头文件 int main(int argc, const char * argv[]) ...

  4. oc语言学习之基础知识点介绍(三):类方法、封装以及继承的介绍

    一.类方法的使用 /* 像我们之前学的方法,必须先实例化这个类的对象才能调用这个方法,类方法不用实例化对象,直接调用这个方法. 之前学的方法调用的语法: [对象名 方法名]; //对象方法 类方法: ...

  5. c语言学习之基础知识点介绍(三):scanf函数

    本节继续介绍c语言的基础知识点. scanf函数:用来接收用户输入的数据. 语法:scanf("格式化控制符",地址列表); 取地址要用到取地址符:&(shift+7) 例 ...

  6. c语言学习之基础知识点介绍(二):格式化控制符和变量的补充

    上节简单介绍了c语言中的一些基础知识点,本节将对之前介绍的不够详细的知识点进行补充. 格式化控制符的消息介绍: %d的其他控制符: 1.%md:m代表这个整数位占用多少位,m是一个整数.实际数字不足的 ...

  7. c语言学习之基础知识点介绍(十):内存空间模型、地址解释及指针变量

    一.内存 /* 内存: 存在内存里的. 内存分了N多个小空间,每个小空间1个字节 每个小空间有它自己的地址.每个地址之间差1 int类型占用4个字节,等于占了4个空间(有4个地址),不需要记住4个地址 ...

  8. c语言学习之基础知识点介绍(四):算术运算符和逗号表达式

    本节主要介绍c语言中运算符. 运算符主要分为四类: 1.算术运算符 加(+),减(-),乘(*),除(/),取余(%,两数相除,得到余数) 2.关系运算符 3.逻辑运算符 4.换位运算符 下面将依次介 ...

  9. c语言学习之基础知识点介绍(十四):指针的进阶

    一.指针的加.减法运算 /* 1.加法运算 1).可以跟整数进行加法运算,得到的还是一个地址 公式: 地址 + 1 = 地址 + 1 * 类型所占的字节数 地址 + n = 地址 + n * 类型所占 ...

随机推荐

  1. Sql Server 日期格式化函数

    Sql Server 中一个非常强大的日期格式化函数Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AMSelect CONVE ...

  2. 图片过大导致OOM

    原文:http://www.codeceo.com/article/android-load-image-oom.html 一.分析 在加载图片过程中出现的OOM的几种情况: 1. 加载的图片过大 2 ...

  3. 微信开发 提示 Redirect&lowbar;uri参数错误解决方法

    出现这个问题有多种原因: 1.没有配置网页授权 我们可以根据微信的开发者文档http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d ...

  4. mysql中的timestamp类型时间比较:unix&lowbar;timestamp函数

    在mysql中,某字段的类型设置为了timestamp,那么我们现在希望取出指定时间段的记录,该如何做呢? 在php中有time()和strtotime()来进行日期和时间戳的格式化,而在mysql中 ...

  5. JQuery Smart UI

    JQuery Smart UI 个人开发的一套使用htm+js的开发框架 SmartUI2.0后续声明 摘要: 感谢很多朋友关注,因为今年一直在另外一个公司做顾问,网络环境管制相当严格,所以一直没有更 ...

  6. PHP聊天室开源系统workerman-chat

    PHP聊天室开源系统workerman-chat (2015-01-23 09:07:50) 转载▼ http://www.workerman.net/ http://www.workerman.ne ...

  7. Linux中以单容器部署Nginx&plus;ASP&period;NET Core

    引言 正如前文提到的,强烈推荐在生产环境中使用反向代理服务器转发请求到Kestrel Http服务器,本文将会实践将Nginx --->ASP.NET Core 部署架构容器化的过程.   Ng ...

  8. 如何让form表单在enter键入时不提交

    今天在做我的一个小玩意 在线聊天工具的时候 form表单只有一个text和一个button每当我键入enter的时候就刷新.很是郁闷,直接在form上onsumbit=false.才行. 下面是我查询 ...

  9. 20155339 2016-2017-2 《Java程序设计》第9周学习总结

    20155339 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 JDBC入门 JDBC简介 JDBC全名Java DataBase Connectivity ...

  10. 03-nginx虚拟主机配置

    不想用kill命令控制nginx也行,但是其他命令没有信号的命令丰富.重读配置文件不用重启nginx(软重启).完全可以使用stop(强制退出).quick(优雅退出).reopen(重新打开日志). ...