OC基础--继承
继承的基本概念:
现实生活中的继承:
人类是一个基类(也称做父类),通常情况下所有人类所共同具备的特性,如有手有脚能吃能喝
按照生活常规,我们继续给人类来细分的时候,我们可以分为学生类 工人类等,学生类和工人类同样具备手 脚 吃 喝等特性,而这些特性是所有人类所共有的,那么就可以让学生或工人类继承人类,这样当建立学生类和工人类的时候我们无需再定义人类中已经有的成员和方法,而只需要描述学生类和工人类所特有的特性即可。
学生类和工人类的特性是由在人类原有特性基础上增加而来的,那么学生类和工人类就是人类的派生类(也称做子类)。以此类推,层层递增, 这种子类获得父类特性的概念就是继承
OC中的继承关系
- B类继承A类,那么B类将拥有A类的所有属性和方法,此时我们说A类是B类的父类,B类是A类的子类
- C类继承B类,那么C类将拥有B类中的所有属性和方法,包括B类从A类中继承过来的属性和方法,此时我们说B类是C类的父类,C类是B类的子类
- 注意:
- 基类的私有属性能被继承,不能在子类中访问。
- OC中的继承是单继承:也就是说一个类只能一个父类,不能继承多个父类
- 子类与父类的关系也称为isA(是一个)关系,我们说 子类isA父类,也就是子类是一个父类,比如狗类继承动物类,那么我们说狗isA动物,也就是狗是一个动物。再如汽车继承交通工具,那么们说汽车isA交工工具,也就是汽车是一个交通工具
- 继承的合理性:引用《大话西游》里的一句话来描述继承的合理性。“人是人他妈生的,妖是妖他妈生的!” 以此类推 人妖是….
继承是代码重用的重要方式之一
- 来感受一下, 我们定义个学生类和一个工人类 如果不使用继承, 代码如下:
学生类声明文件.h:
#import <Foundation/Foundation.h> @interface Student : NSObject
{
// 姓名
NSString * _name;
// 年龄
int _age;
// 学号
int _studengNO;
// 身份
NSString * _identity;
}
- (void) setName:(NSString *) name;
- (NSString *) name;
- (void) setAge: (int) age;
- (int) age;
- (void) setStudentNO: (int) studentNO;
- (int) studentNO;
- (void) setIdentity: (NSString *) identity;
- (NSString *) identity;
// 吃
- (void) eat;
// 学习
- (void) study;
@end
学生类实现文件.m:
#import "Student.h" @implementation Student
- (void)setName:(NSString *)name{
_name = name;
}
- (NSString *)name{
return _name;
}
- (void)setAge:(int)age{
_age = age;
}
- (int)age{
return _age;
}
- (void)setStudentNO:(int)studentNO{
_studengNO = studentNO;
}
- (int)studentNO{
return _studengNO;
}
- (void)setIdentity:(NSString *)identity{
_identity = identity;
}
- (NSString *) identity{
return _identity;
}
// 吃
- (void)eat{
NSLog(@"吃东西");
}
// 学习
- (void)study{
NSLog(@"学习");
}
@end
工人类声明文件.h:
#import <Foundation/Foundation.h> @interface Worker : NSObject
{
// 姓名
NSString * _name;
// 年龄
int _age;
// 工号
int _workNO;
// 身份
NSString * _identity;
}
- (void) setName: (NSString *) name;
- (NSString *) name;
- (void) setAge: (int) age;
- (int) age;
- (void) setWorkNO: (int) workNO;
- (int) workNO;
- (void) setIdentity: (NSString *) identity;
- (NSString *) identity;
// 吃
- (void) eat;
// 学习
- (void) study;
// 工作
- (void) work;
@end
工人类实现文件:
#import "Worker.h" @implementation Worker
- (void)setName:(NSString *)name{
_name = name;
}
- (NSString *)name{
return _name;
}
- (void)setAge:(int)age{
_age = age;
}
- (int)age{
return _age;
}
- (void)setWorkNO:(int)workNO{
_workNO = workNO;
}
- (int)workNO{
return _workNO;
}
- (void)setIdentity:(NSString *)identity{
_identity = identity;
}
- (NSString *) identity{
return _identity;
}
// 吃
- (void)eat{
NSLog(@"吃东西");
}
// 学习
- (void)study{
NSLog(@"学习");
}
// 工作
- (void)work{
NSLog(@"上班了 干活");
}
@end
比较一下上面的代码 看看有多少是重复的:
声明文件中重复部分:
属性:
// 姓名
NSString * _name;
// 年龄
int _age;
// 身份
NSString * _identity;
行为:
- (void) setName:(NSString *) name;
- (NSString *) name;
- (void) setAge: (int) age;
- (int) age;
- (void) setIdentity: (NSString *) identity;
- (NSString *) identity;
// 吃
- (void) eat;
// 学习
- (void) study;
实现文件中重复部分:
- (void)setName:(NSString *)name{
_name = name;
}
- (NSString *)name{
return _name;
}
- (void)setAge:(int)age{
_age = age;
}
- (int)age{
return _age;
}
- (void)setIdentity:(NSString *)identity{
_identity = identity;
}
- (NSString *) identity{
return _identity;
}
// 吃
- (void)eat{
NSLog(@"吃东西");
}
// 学习
- (void)study{
NSLog(@"学习");
}
得到的结果是:
学生类中就一个学号在工人类中没有
工人类中就一个工号和一个工作的行为在学生类中没有
其余部分都是重复代码
如果还要添加几个其他类: 如学前期的幼儿类 退休后的老人类等等 那么上面那些重复的代码还得重复好几遍 复制粘贴都感觉累有木有
现在我们来添加一个Person类 人类中定义属性有 姓名 (name) 年龄(age) 身份(identity) 行为有 吃(eat) 学习(study)
使用继承关系后再来看看代码:
Person类声明文件:
#import <Foundation/Foundation.h> @interface Person : NSObject
{
// 姓名
NSString * _name;
// 年龄
int _age;
// 身份
NSString * _identity;
}
- (void) setName:(NSString *) name;
- (NSString *) name;
- (void) setAge: (int) age;
- (int) age;
- (void) setIdentity: (NSString *) identity;
- (NSString *) identity;
// 吃
- (void) eat;
// 学习
- (void) study;
@end
Person类实现文件:
#import "Person.h" @implementation Person
- (void)setName:(NSString *)name{
_name = name;
}
- (NSString *)name{
return _name;
}
- (void)setAge:(int)age{
_age = age;
}
- (int)age{
return _age;
}
- (void)setIdentity:(NSString *)identity{
_identity = identity;
}
- (NSString *) identity{
return _identity;
}
// 吃
- (void)eat{
NSLog(@"吃东西");
}
// 学习
- (void)study{
NSLog(@"学习");
}
@end
学生类声明文件:
#import <Foundation/Foundation.h>
#import "Person.h" @interface Student : Person
{
// 学号
int _studengNO;
}
- (void) setStudentNO: (int) studentNO;
- (int) studentNO;
@end
学生类实现文件:
#import "Student.h" @implementation Student
- (void)setStudentNO:(int)studentNO{
_studengNO = studentNO;
}
- (int)studentNO{
return _studengNO;
}
@end
工人类的声明文件:
#import <Foundation/Foundation.h>
#import "Person.h"
@interface Worker : Person
{
// 工号
int _workNO;
}
- (void) setWorkNO: (int) workNO;
- (int) workNO;
// 工作
- (void) work;
@end
工人类的实现文件:
#import "Worker.h" @implementation Worker
- (void)setWorkNO:(int)workNO{
_workNO = workNO;
}
- (int)workNO{
return _workNO;
}
// 工作
- (void)work{
NSLog(@"上班了 干活");
}
@end
好了, 现在再来看看代码: 我们的代码中多了一个Person类的声明和实现文件 在这个类中声明定义的就是我们之前学生类和工人类中重复的那一部分.
"B类继承A类,那么B类将拥有A类的所有属性和方法" 就是说如果 我们让学生类和工人类都继承自Person类 , 那么就算我们在学生类中和工作类中都没有声明那些姓名 年龄 吃 学习之类的属性和方法, 这两个类也能从Person类中得到这些行为属性. 而在学生类中只需要声明学生类特有的学号属性, 工人类中只需要声明工人类特有的工号,工作这种特有的行为属性即可, 这样子在学生类和工人类中得代码看起来简洁了很多, 而且以后如果我们需要再添加什么婴儿类 老人类, 也只需要在相关类中添加他们特有的行为属性就行了.
在这个例子里, Person类就是父类 学生类和工人类就是Person类的子类, 需要注意的是OC也是单继承的, 毕竟咱都只有一个父亲是吧, (呃 那个 干爹不算) , 在父类中定义的所有行为属性, 子类都能继承过去, 而在子类中还可以添加他特有的行为属性, 也就是说我爸有的 我都有, 我有的, 我爸不一定有(例如: 我会打Dota 我爸不会 ).
当我们发现两个类中有定义很多重复的行为属性的时候, 便可以把这些重复的部分都抽取出来当一个父类; 继承对代码的重用性和可扩展性 , 看上面例子体会一下吧
OC中继承的实现格式:
@interface 子类名称 : 父类名称 @end
记得导入父类头文件
继承:
当B类继承A类, 那么B类就拥有A类所有的属性和方法(类方法/对象方法)
优点:
提高代码的复用性
可以让类与类之间产生关系, 正是因为继承让类与类之间产生了关系所以才有了多态
缺点: 增加了代码之间的耦合性
注意:
不要以为继承可以提高代码的复用性, 以后但凡发现多个类当中有重复代码就抽取一个父类
只要满足一定的条件我们才能使用继承
条件: XXXX 是 XXX / 某某某 is a 某某某 (继承是 '是' 的关系 接口(协议) 是 '有' 的关系)
方法的重写:
- 在子类中实现与父类中同名的方法,称之为方法重写( 方法名相同 方法体不同 子类提供新的实现)
- 重写以后当给子类发送这个消息的时候,执行的是在子类中重写的那个方法,而不是父类中的方法
- 如果想在子类中调用被子类重写的父类的方法,可以通过super关键字
- 使用场景:当从父类继承的某个方法不适合子类,可以在子类中重写父类的这个方法
方法重写: 子类从父类继承了父类的方法(行为) 但是不想用父类的实现体 可以自己提供新的实现覆盖掉父类的实现
举例: 我爸会打人 我从我爸那也继承了打人的行为 我爸打人用拳头打 但是我感觉用拳头打不爽 就可以用自己的方式去打 (如用板砖砸) 这样虽然都是打人的方法 但是我用板砖打覆盖了从我爸那继承来的用拳头打 这样方法名相同 但是方法的实现子类和父类不同(子类的实现覆盖了父类的实现) 就是方法的重写
在上面例子中我们来重写父类学习的方法:
Person类中得学习方法实现:
// 学习
- (void)study{
NSLog(@"学习");
}
工人类重写父类的学习方法:
// 学习
- (void)study{
NSLog(@"我们在职人员通过上网来学习");
}
学生类重写父类的方法:
// 学习
- (void)study{
[super study];
NSLog(@"我们学生都通过去上课来学习");
}
继承中方法调用的顺序:
1、在自己类中找
2、如果没有,去父类中找
3、如果父类中没有,就去父类的父类中
4、如果父类的父类也没有,就还往上找,直到找到基类(NSObject)
5、如果NSObject都没有就报错了
以上如果找到了就执行这个方法,就不再往后查找了
继承的注意事项:
- 子类不能定义和父类同名的成员变量,私有成员变量也不可以;因为子类继承父类,子类将会拥有父类的所有成员变量,若在子类中定义父类同名成员变量 属于重复定义。
- OC类支持单一继承,不支持多继承;也就是说一个类只能有一个直接父类
- OC类支持多层继承
super关键字:
概念: super是个编译器的指令符号,只是告诉编译器在执行的时候,去调谁的方法
作用: 直接调用父类中的某个方法
super在对象方法中,那么就会调用父类的对象方法 super在类方法中,那么就会调用父类的类方法
使用场合: 子类重写父类的方法时想保留父类的一些行为
OC基础--继承的更多相关文章
- OC基础:继承.初始化方法,便利构造器 分类: ios学习 OC 2015-06-16 19:27 84人阅读 评论(0) 收藏
继承: 1.单向继承,一个类只能有一个父类,一个父类可以有多个子类. 2.单向继承,基类(根类)是OSObject 3.子类可以继承父类的属性和方法 当父类的方法不满足子类的需求时,子类可以重写父类的 ...
- OC基础5:继承
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.根类即是最顶层的类,父类也可称为超类: ...
- 四.OC基础--1.文档安装和方法重载,2.self和super&static,3.继承和派生,4.实例变量修饰符 ,5.私有变量&私有方法,6.description方法
四.OC基础--1.文档安装和方法重载, 1. 在线安装 xcode-> 系统偏好设置->DownLoads->Doucument->下载 2. 离线安装 百度xcode文档 ...
- iOS 阶段学习第11天笔记(OC基础知识)
iOS学习(OC语言)知识点整理 一.OC基础知识 1)#import 用于导入头文件,预处理阶段加载引用,只加载一次. 2)OC 依赖于Foundation框架下的头文件Foundation.h, ...
- OC基础笔记目录
OC基础(1) Objective-C简介 OC和C对比 第一个OC程序 面向对象思想 OC基础(2) 类与对象 类的设计 第一个OC类 对象方法的声明和实现 类方法的声明和实现 OC基础(3) 对象 ...
- OC - 2.OC基础知识介绍
一.基础语法 1> OC语言和C语言 C语言是面向过程的语言,OC语言是面向对象的语言 OC语言继承了C语言,并增加了面向对象的思想 以下内容只介绍OC语言与C语言的不同之处 2> 关键字 ...
- OC基础 代理和协议
OC基础 代理和协议 1.协议 (1)oc语言中得协议:一组方法列表,不需要我们自己实现,由遵守协议的类来实现协议所定制的方法. (2)协议的使用步骤:制定协议-->遵守协议-->实现协议 ...
- OC基础 类的三大特性
OC基础 类的三大特性 OC的类和JAVA一样,都有三大特性:继承,封装,多态,那么我们就来看一下OC中类的三大特性. 1.继承 继承的特点: (1)子类从父类继承了属性和方法. (2)子类独有的属 ...
- OC基础 点语法的使用
OC基础 点语法的使用 1.创建一个Student类继承于NSObject,Student.h文件 #import <Foundation/Foundation.h> @interface ...
随机推荐
- NE Upgrade python script. Need to write a Tkinter GUI for it
# -*- coding: utf-8 -*-#from ftplib import FTP __authour__='CC' import osimport telnetlibimport time ...
- linux安装配置apk打包程序gradle+jdk+Android_sdk+python自动化编译脚本
安装gradle: 1.下载gradle包 去这里下载需要的tar.gz包:https://services.gradle.org/distributions/ 2.解压 tar zxvf gradl ...
- Kerberos是怎么工作的?
Kerberos是一种计算机网络授权协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证. 采用客户端/服务器结构,并且能够进行相互认证,即客户端和服务器端均可对对方进行身份认证. 关键要素 ...
- Node.js学习-1
关于node.js 首先,node.js不是一门语言,是一个平台.因为在以前,javascript主要是用于网页的交互,所以必须依附于浏览器存在,只有在浏览器上才能运行javascript. 后来ja ...
- Scrum Meeting 13-20151221
任务安排 姓名 今日任务 明日任务 困难 董元财 无(数据库) 网络连接框架优化 无 胡亚坤 无(数据库) 优化商品搜索 无 刘猛 无 无 马汉虎 无 无 赖彦俞 无 无 燃尽图 团队照片 暂无 代码 ...
- mysql 正则篇
一.SQL模式 SQL的模式匹配允许你使用“_”匹配任何单个字符,而“%”匹配任意数目字符(包括零个字符).在 MySQL中,SQL的模式缺省是忽略大小写的.下面显示一些例子.注意在你使用SQL模式时 ...
- python学习--字符串
python的字符串类型为str 定义字符串可以用 ‘abc' , "abc", '''abc''' 查看str的帮助 在python提示符里 help(str) python基于 ...
- java中异常抛出后代码是否会继续执行
为了回答这个问题,我编写了几段代码测试了一下,结果如下: 代码1:throw new Exception("参数越界"); System.out.println(" ...
- Dubai Princess and Prince!
萨拉玛公主,生于1999年 哈曼丹王子 玛丽亚姆公主,出生于1991年
- BIOS MCSDK 2.0 学习笔记(二)————使用Platform Library创建工程
[TOC] Platform Library提供了一组适用于开发板的API函数.我们可以使用它来快速入手开发板. 1.启动CCS,建立一个空的工程 2.添加include路径 "C:\Pro ...