Objective-c 知识总结 -- 继承


知识盲点:

  • OOP 面向对象编程(Object Oriented Programming,OOP)

  • Unified Modeling Language (UML)

  • Inheritance 继承

  • Syntax 语法

  • 重构(Refactoring):Moving and simplifying code this way is called refactoring, a subject that is quite trendy in the OOP community.(移动或简化代码称为重构)When you refactor, you move code around to improve the architecture, as we did here to eliminate duplicate code, without changing the code’s behavior or results.(不改变代码的最终效果)

  • polymorphism 多态


知识点:

  • 为什么要使用继承?

  • 继承在Objective-C中的语法表示?


  • 为什么要使用继承?

  • 假设有两个类 圆、方形

圆(.h):


方形(.h):



观察发现,它们属性和方法声明是相同的,都有 填充色(fillcolor)、尺寸+位置(bounds)、绘制方法;

如此相同的声明,除了类名不同,其它都一样?那么可否把它们的声明封装(抽象)起来,但类名(具体细节)又可以不一样?
先保存这种疑问,来看看(.m)文件。

圆(.m):


方形(.m):


观察发现,圆和方形的 setFillColor: 和 setBounds: 方法的实现是一样的,唯一的不同就是它们的绘制方法 draw: ;

通过观察分析可以得知,如果要把圆、方形封装起来,那么就要保证具体的实现可以有不一样(draw:)方法;简单来说就是,封装(抽象)不对细节进行限制,只对声明进行限制,就是只告诉你叫什么,不告诉你是什么,要确定是什么,根据不同的类型(圆或者方形)来确定。

结:我们都知道的,圆和方形都是几何图形,而面向对象编程,就是对现实世界的抽象,而圆和方形的抽象就是几何图形;换种方式描述就是,几何图形是圆、方形的父集(父亲),圆、方形是几何的子集(子女)。

抽象过程:


继承 :Inheritance in OOP means that a class acquires features from another class, its parent or superclass.(一个类(子类)的特性(属性+方法+协议......)来源于另一个类(父类))

  • 继承在Objective-C中的语法表示?

首先,通过上面的分析,圆、方形的特性可以由几何图形来提供,也就是说圆、方形是可以继承于几何图形的。


分析代码:

@interface 子类 : 父类
// 新特性
@end

@interface 和 @end 是一对,不能拆开前者表明继承的开始,后者表明继承的结束;
子类,就是新创建的类的类名(Circle / Rectangle);

父类,要继承的类(Shape);
//新特性:可以定义自己的特性
上面 代码的意思:Circle/Rectangle继承于Shape(拥有Shape的特性);

Shape(.h):


Shape(.m):


代码分析:
@interface Shape : NSObject ,NSObject是 Cocoa Touch 框架的根类,所有类的父类;

{...},是声明实例变量;

@implementaion 和 @end 是一对,表明对方法的实现;
观察 Shape 的(.m)文件可以发现,只有 draw 方法是空的,因为我们清楚圆和方形的绘制方式是不同的(相当于等待子类自己去实现),而颜色填充和尺寸位置的表现方式是一样的;

圆的绘制方法:


方形的绘制方法:


疑问:

  • 一个类可以继承多个父类吗?

  • 子类可以直接使用父类的特性?

  • 子类重新实现了绘制方法,那么编译器会优先使用父类的方法还是子类的呢?

  • 子类可以修改父类的特性吗?

一些继承的术语:

  • superclass(超类):the class you’re inheriting from.(你所继承的类,几何图形)

  • Parent class(父类),superclass 的另一种说法

  • subclass (子类):the class doing the inheriting(做继承这个行为的类,圆、方形)

  • Child class (孩子类):subclass 的另一种说法

  • override (重写):an inherited method when you want to change its implementation(重新实现继承而来的方法)

疑问解答:
1.Objective-C不能实现多继承,就是说(class : class1,class2...)是不允许的;

2.父类的实例变量能否被子类使用,取决于实例变量的权限修饰符


默认是@protected,子类可以继承父类的实例变量,但是是否可以访问,就看权限修饰符;

如果是使用属性@property进行声明的,就要查看相应的属性修饰符;

3.方法调度优先级:

When code sends a message, the Objective-C method dispatcher searches for the method in the current class. If the dispatcher doesn’t find the method in the class of the object receiving the message, it looks at the object’s superclasses.(当一个类发送消息的时候,调度器会首先从当前类中的方法列表中查找相应的消息方法,如果发现当前没有找到,就会进入到当前类的父类中进行查找如果有就执行,如果没有就继续向父类查找直到找到 NSObject 类还是没有的话,就直接报错。)

例子:
假设给圆这个类的实例设置颜色如下:
[Circle setFillColor:kRedColor];

未继承Shape

继承了Shape


4.子类可以添加新的实例变量

假设创建一个新类:RoundedRectangle(圆角矩形)
首先它是几何图形,也是矩形(方形),但是比矩形多了一个圆角;所以它可以直接继承几何图形,也可以继承矩形;

创建一个 RoundedRectangle 对象实例,它的实例变量在内存的分布是:

内容分析:
“isa”:The NSObject instance variable is called isa because inheritance sets up an “is a” relationship between the subclass and the superclass; that is, a Rectangle is a Shape, and a Circleis a Shape. Code that uses a Shape can also use a Rectangle or Circle instead.(isa意指 “是一个” ,如:圆是一个几何图形,矩形是一个几何图形,表明一种包含关系);isa 是 NSObject 的实例变量;

“fillcolor bounds”:Shape 的实例变量,因为 RoundedRectangle 继承了 Shape 所以有这两个特性,而 fillcolor 是先于 bounds 被定义的,所以它处于上方;
“radius”:圆角是 RoundedRectangle 这个类特有的特性,因为最后被定义所以处于最后的位置;

注:每一个实例变量都有一个隐藏的实例(元类的实例) self

完整的图是:


内容分析:
所有的实例变量是分配在一块内存区域中的,而且是有序的、每一个实例变量的内存大小是已经固定的;

self 就是指向内存区域的首地址,只要根据各个实例变量的内存大小进行移位就可以正常访问到每一个实例变量;(The compiler works its magic by using a “base plus offset” (首地址+偏移量)mechanism. Given the base address of an object—that is, the memory location of the first byte of the first instance variable—the compiler can find all other instance variables by adding an offset to that address.)

???问题:This does lead to problems over time. These offsets are now hard-coded into the program generated by the compiler. Even if Apple’s engineers wanted to add another instance variable to NSObject, they couldn’t, because that would change all of the instance variable offsets. This is called the fragile base class problem(脆弱的基类问题). Apple has fixed this problem with the new 64-bit Objective-C runtime introduced with Leopard, which uses indirection for determining ivar locations.

从两张图可以知道,当一个类的实例化后,它的实例对象在内存的位置(地址)是固定的,而且大小也是固定的,也就是 self 每一次的偏移量也是固定的;

那么问题来了,假设我现在又想增加一个实例变量呢,如果是添加在 radius 的后面,内存的地址没有发生变化,如果添加在 fillcolor / bounds / radius 的中间呢?那么内存地址就发生了改变, self 的每一交偏移量就发生了改变;

所以在后来苹果使用了间接的手段对 ivar (实例变量)进行内存测定,从而杜绝实例对象在初始化化后实例变量频繁修改所引起的内存变化;

5.修改(重写)父类的方法(特性)

When classes such as Circle and Rectangle implement their own draw methods, we say that they have overridden the draw method.

在文章的开始时,就有 Circle / Rectangle 两个类,它们都是 Shape 的子类,而且它们都实现了自己的 draw 方法,而这种行为就是重写(重新实现 draw 方法);

注:When a draw message is sent to a circle object, the method dispatcher runs the overridden method—Circle’s implementation of draw. Any implementation of draw defined by a superclass, such as Shape, is completely ignored.(由于调度优先级的存在,调度会先从子类开始到根类,而子类一旦有相应的消息方法,那么就会直接调度而不会再进行深一层的查找(继承链),会直接忽略父类的相同方法)

???问题:假设现在要把所有创建的圆实例对象的红色填充修改为绿色填充?

第一种就是,每一个实例对象都调用 [ Circle setFillColor:kGreenColor ];直接进行设置(实际上是调用了父类的颜色填充方法,因为父类的颜色填充方法没有颜色判断功能,只是单纯的颜色填充,所以导致每一个实例对象都要自己去设置颜色,而且 Circlr 还无法保证设置是否符合要求);

第二种就是, Circle 类自己写一个设置颜色的方法,只要不是绿色的都改成绿色,再进行颜色填充;(重写 父类方法)

看代码:


代码分析:
"super setFillColor":这句代码就是使用父类的填充颜色方法;当然自己重新写也可以;

重写的方法(setFillColor:)的调度过程:

注:如果重写了父类的方法,建议还是调用 [ super setFillColor:c ];这样可以保证父类做完它应该做的事,避免不必要的错误。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容