Objective-C学习笔记_继承、初始化方法、便利构造器

一、继承

继承的上层:父类,继承的下层:子类。继承是单向的,不能相互继承。继承具有传递性:A继承于B,B继承于C,A具有B和C的特征和?为。子类能继承父类全部的特征和行为。

例题

打僵尸。需求:

1、定义普通僵尸类:

实例变量:僵尸总血量、僵尸每次失血量。

方法:初始化方法(总血量)、被打击失血、死亡。

2、定义路障僵尸类:

实例变量:僵尸总血量、僵尸每次失血量,道具,弱点。

方法:初始化方法(总血量)、被打击失血、失去装备、死亡。

3、定义铁桶僵尸类:

实例变量:僵尸总血量、僵尸每次失血量,道具,弱点。

方法:初始化方法(总血量)、被打击失血、失去装备、死亡。

4、在main.m中创建普通僵尸对象,设置总血量50,每次失血量为 3,没有道具。

5、在main.m中创建路障僵尸对象,设置总血量80,每次失血量为 2,设置道具为路障。

6、在main.m中创建铁桶僵尸对象,设置总血量120,每次失血量为 1,设置道具为铁桶。

如果定义三个类:普通僵尸、路障僵尸、铁桶僵尸。它们会有很多重复的实例变量和方法,这不仅是体力活,而且也不科学。面向对象提供了继承语法,能?大简化代码。把公共的方法和实例变量写在父类里,子类只需要写?己独有的实例变量和方法即可。继承既能保证类的完整,又能简化代码。

继承实现

#import <Foundation/Foundation.h>
              /* 子类 */     /* 父类 */
@interface OrdinaryZombie : NSObject
@end
#import "OrdinaryZombie.h"
              /* 子类 */        /* 父类 */
@interface RoadblockZombie : OrdinaryZombie
@end

继承特点

Objective-C中只允许单继承。没有父类的类称为根类,Objective-C中的根类是NSObject(祖宗)。

继承的内容:所有实例变量和方法。如果子类不满意父类方法的实现,可以重写(overwrite)父类的方法。

继承树

继承中?法的执行

self、super

self和super是Objective-C语言中的关键字。

super是编译器指令,并非对象。

作用:给super发消息,可以执?父类中实现的方法。

子类可以重写父类的方法,即:子类既有?己的实现,?有父类继承下来的实现,如果想使用父类的实现,向super发送消息。

self作用:调用自身的方法和属性,始终代表调用方法的对象。

self和super使用的简单示例代码如下:

- (instancetype)initWithName:(NSString *)name
                         sex:(NSString *)sex
{
    /*
     * 详细解释[super init]
     * 父类中定义的实例变量通过向super请求初始化方法来得到初始化
     * 向super请求初始化方法的消息连接起了所有继承树上的对象
     * 父类的变量会比子类的变量先得到初始化
     * 例如: CollegeStudent对象在初始化时, 会依次对NSObject, Student, CollegeStudent进行初始化
     * 关于初始化方法, 请查阅本博文下面内容
     */
    self = [super init];
    if (self) {
        _name = name;
        _sex = sex;
    }
    return self;
}

二、初始化方法

使用Objective-C创建对象分为两步:

  1. 内存分配(开辟空间):为新对象动态的分配一段内存地址。
  2. 初始化:为这段内存空间赋初始值。

初始化方法在对象的整个生命周期里只使用一次。初始化方法命名一般以init开头;初始化方法可以在对象创建的时候给实例变量赋初值;初始化方法的返回值只能是id(或instancetype)或本类对象,不能是void。一个类可以有多个初始化方法。

完整的初始化方法,示例代码如下:

- (instancetype)initWithName:(NSString *)name
                         sex:(NSString *)sex
{
    // 给super发送init消息: 即执行父类中实现的init方法
    self = [super init];
    if (self) {
        // 初始化设置
        _name = name;
        _sex = sex;
    }
    // 返回初始化完成的对象
    return self;
}

注意:

  • 学习继承之前,类与类之间没有关联,因此初始化方法没有self = [super init];字样,从而为实例变量逐一赋值。
  • 学习继承之后,?类中声明了共有的实例变量。作为父类,应该有自己的初始化方法,为这些共有的实例变量赋初值。
  • 子类定义了除父类中公共实例变量之外的实例变量。在?身的初始化方法中,优先向super发送init消息,初始化公共变量,初始化成功之后,再初始化?身特有变量,从而完成全部实例变量的初始化。

初始化过程

  1. 子类的初始化方法中,优先调?父类的初始化方法。
  2. ?类的初始化?法中再调用其父类的初始化方法,依次往上调用,直至NSObject类。
  3. 处于最上层的初始化完成之后,回到第二层的初始化方法中,完成第二层的初始化。第二层的初始化完成之后,回到第三层的初始化方法中,依次执?初始化方法,直到本类的初始化方法完成。

初始化?法的特征

  • 初始化方法是 “-”号方法。
  • 返回值类型是 id 或者 instancetype。
  • 以init开头。
  • 可以带0到多个参数。
  • 内部实现:先执?super的初始化方法,再初始化??变量,return self。

三、便利构造器

便利构造器在初始化方法的基础上进行了封装,即封装了对象的创建过程。便利构造器是“+”号方法,返回 本类型 的实例,方法名以类名开头。可以有0到多个参数。内部实现,封装了alloc和初始化方法。使?起来更加简洁。

便利构造器的实现

1.声明和实现便利构造器。

+ (instancetype)personWithName:(NSString *)name
                           sex:(NSString *)sex;

+ (instancetype)personWithName:(NSString *)name
                           sex:(NSString *)sex
{
    Person *person = [[Person alloc] initWithName:name sex:sex];
    return person;
}

2.使?便利构造器创建对象。

Person *person = [Person personWithName:@"小红" sex:@"女"];

其实,便利构造器的便利不仅是代码量的减少,也是对内存操作的便利,如果用便利构造器创建了一个对象,则在使用完毕后不用去释放该对象,出了自动释放池后,对象被自动销毁,在自动释放池销毁之前,我们持有对象,不用理会什么时候释放该对象(这是Objective-C内存管理的内容,博主会在后续的博文中详细说明)。


附录

开篇例题“打僵尸”的代码实现

本例题利用继承实现,题目要求较为简单,请仔细阅读代码。

普通僵尸类 OrdinaryZombie.h 代码如下:

#import <Foundation/Foundation.h>

@interface OrdinaryZombie : NSObject
{
@protected
    NSInteger _fullOfBlood; /* 总血量 */
    NSInteger _lossOfBlood; /* 每次失血量 */

    NSString *_equipment; /* 道具 */
    NSString *_weakness; /* 弱点 */
}

/* 实例变量setter, getter方法 */
- (void)setFullOfBlood:(NSInteger)fullOfBlood;
- (NSInteger)fullOfBlood;

- (void)setLossOfBlood:(NSInteger)lossOfBlood;
- (NSInteger)lossOfBlood;

- (void)setEquipment:(NSString *)equipment;
- (NSString *)equipment;

- (void)setWeakness:(NSString *)weakness;
- (NSString *)weakness;

/* 初始化方法(总血量) */
- (id)initWithBlood:(NSInteger)fullOfBlood;

/* 被打击失血 */
- (void)attacked;

/* 死亡 */
- (void)death;

/* 失去装备 */
- (void)loseEquipment;
@end

普通僵尸类 OrdinaryZombie.m 代码如下:

#import "OrdinaryZombie.h"

@implementation OrdinaryZombie
- (void)setFullOfBlood:(NSInteger)fullOfBlood
{
    _fullOfBlood = fullOfBlood;
}

- (NSInteger)fullOfBlood
{
    return _fullOfBlood;
}

- (void)setLossOfBlood:(NSInteger)lossOfBlood
{
    _lossOfBlood = lossOfBlood;
}

- (NSInteger)lossOfBlood
{
    return _lossOfBlood;
}

- (void)setEquipment:(NSString *)equipment
{
    _equipment = equipment;
}

- (NSString *)equipment
{
    return _equipment;
}

- (void)setWeakness:(NSString *)weakness
{
    _weakness = weakness;
}

- (NSString *)weakness
{
    return _weakness;
}

- (id)initWithBlood:(NSInteger)fullOfBlood
{
    _fullOfBlood = fullOfBlood;
    return self;
}

- (void)attacked
{
    _fullOfBlood -= _lossOfBlood;
    if (_fullOfBlood <= 0) {
        _fullOfBlood = 0;
    }
    NSLog(@"剩余血量: %ld", _fullOfBlood);
}

- (void)death
{
    NSLog(@"普通僵尸, 死亡");
}

- (void)loseEquipment
{
    NSLog(@"失去装备");
}
@end

路障僵尸类 RoadblockZombie.h 代码如下:

#import "OrdinaryZombie.h"

@interface RoadblockZombie : OrdinaryZombie

@end

路障僵尸类 RoadblockZombie.m 代码如下:

#import "RoadblockZombie.h"

@implementation RoadblockZombie
- (void)death
{
    NSLog(@"路障僵尸, 死亡");
}

- (void)loseEquipment
{
    NSLog(@"路障僵尸");
    [super loseEquipment];
}
@end

铁桶僵尸类 MetalBucketZombie.h 代码如下:

#import "OrdinaryZombie.h"

@interface MetalBucketZombie : OrdinaryZombie

@end

铁桶僵尸类 MetalBucketZombie.m 代码如下:

#import "MetalBucketZombie.h"

@implementation MetalBucketZombie
- (void)death
{
    NSLog(@"铁桶僵尸, 死亡");
}

- (void)loseEquipment
{
    NSLog(@"铁桶僵尸");
    [super loseEquipment];
}
@end

main.m 代码如下:

#import <Foundation/Foundation.h>
#import "OrdinaryZombie.h"
#import "RoadblockZombie.h"
#import "MetalBucketZombie.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
            /* 普通僵尸 */
        OrdinaryZombie *ordZom = [[OrdinaryZombie alloc] initWithBlood:50];
        /* 每次失血量 */
        [ordZom setLossOfBlood:3];
        while (1) {
            if ([ordZom fullOfBlood] == 0) {
                [ordZom death];
                break;
            }
            [ordZom attacked];
        }

        /* 路障僵尸 */
        RoadblockZombie *roadZom = [[RoadblockZombie alloc] initWithBlood:80];
        /* 每次失血量 */
        [roadZom setLossOfBlood:2];
        /* 装备类型 */
        [roadZom setEquipment:@"路障"];
        while (1) {
            /* 如果剩余50滴血 */
            if ([roadZom fullOfBlood] <= 50) {
                /* 失去装备 */
                [roadZom loseEquipment];
                /* 失血量设置成普通僵尸 */
                [roadZom setLossOfBlood:[ordZom lossOfBlood]];
                break;
            }
            [roadZom attacked];
        }
        while (1) {
            if ([roadZom fullOfBlood] == 0) {
                [roadZom death];
                break;
            }
            [roadZom attacked];
        }

        /* 铁桶僵尸 */
        MetalBucketZombie *metalZom = [[MetalBucketZombie alloc] initWithBlood:120];
        /* 每次失血量 */
        [metalZom setLossOfBlood:1];
        /* 装备类型 */
        [metalZom setEquipment:@"铁桶"];
        while (1) {
            /* 如果剩余50滴血 */
            if ([metalZom fullOfBlood] <= 50) {
                /* 失去装备 */
                [metalZom loseEquipment];
                /* 失血量变成普通僵尸 */
                [metalZom setLossOfBlood:[ordZom lossOfBlood]];
                break;
            }
            [metalZom attacked];
        }
        while (1) {
            if ([metalZom fullOfBlood] == 0) {
                [metalZom death];
                break;
            }
            [metalZom attacked];
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 17:36:43

Objective-C学习笔记_继承、初始化方法、便利构造器的相关文章

OC基础:继承.初始化方法,便利构造器

继承: 1.单向继承,一个类只能有一个父类,一个父类可以有多个子类. 2.单向继承,基类(根类)是OSObject 3.子类可以继承父类的属性和方法 当父类的方法不满足子类的需求时,子类可以重写父类的方法,重写父类的方法,在子类中不需要再次声明. 1.完全重写 2.部分重写   使用super 建立继承关系之后,子类可以继承父类的: 1.实例变量,@[email protected]修饰情况之下 2.公开的方法 一个方法如果在.h中声明了,那么这个方法就是公开的方法,如果没有声明,则是私有的.

No2_2.接口继承多态_Java学习笔记_继承

***类的继承***1.继承的实现extends2.[修饰符] class 子类名 extends 父类名{}3.修饰符一般为:public abstract final4.重写是指父子类之间的关系,子类的方法名与父类的方法名相,那么子类就不能继承父类的方法,称子类的方法重写了父类的方法.5.重写体现了子类补充或者改变父类方法的能力.通过重写,可以使一个方法在不同的子类中表现出不同的行为:6.重写民可以称为覆盖: ***使用super关键字***1.子类可以继承父类的非私有成员变量和成员方法(非

黑马程序员_IOS开发_Objective-C学习笔记_继承和分类

1.什么是继承 继承是面向对象程序的三大特征之一,意思是基于一个类的基础,定义一个新类. 被继承的类成为父类,新类成为子类. 继承的实际例子有许多.例如,一个儿子继承了他父亲,那么他就继承了他父亲的财产. 例如基类是Person,那么我们可以继承Person这个类,产生新的子类Student,Teacher 在这里Person是Student类和Teacher类的父类. 引入继承的概念是有许多好处的: *能够抽取重复代码 *建立了类和类之间的联系 *不改变原来模型的基础上,能够扩展出新的方法 2

python基础教程_学习笔记11:魔法方法、属性和迭代器

魔法方法.属性和迭代器 在python中,有的名称会在前面和后面各加上两个下划线,这种写法很特别.它表示名字有特殊含义,所以绝不要在自己的程序中使用这种名字.在python中,由这些名字组成的集合所包含的方法叫做魔法(或称特殊)方法.如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下被python调用,而几乎没有直接调用它们的必要. 准备工作 为了确保类是新型的,应该把赋值语句__metaclass__=type放在你的模块的最开始,或者(直接或间接)子类化内建类(实际上是类型)ob

C++ Primer Plus学习笔记之继承类的初始化顺序

C++ Primer Plus学习笔记之继承类的初始化顺序 基类的构造函数,析构函数和操作符函数operator=是不能被派生类继承的: 那么,当创建一个派生类对象时,怎样调用基类的构造函数对基类的数据进行初始化呢??? 答案是:构造函数执行时遵行先兄长(基类),再客人(对象成员),后自己(派生类)的顺序: 另一方面,执行析构函数时,先执行派生类的析构函数,再执行基类的析构函数.原因是,对基类的破坏隐含了对派生类的破坏,所以派生类的析构函数必须先执行: #include<iostream> u

C++学习笔记之继承

一.基类和派生类 很多时候,一个类的对象也“是”另一个类的对象,如矩形是四边形,在C++中,矩形类Rectangle可以由四边形类Quad继承而来,于是,四边形类Quad是基类,矩形类Rectangle是派生类.但是如果说四边形一定是矩形显然不对.几个简单的基类和派生类的例子: 基类                         派生类   食物 米饭.面条.水饺   交通工具 汽车.火车.飞机 国家 中国.美国.西班牙 可以看出,每个派生类的对象都是基类的一个对象,并且一个基类可以有很多派生

Java学习笔记之继承

一.继承的基础 在Java术语中,被继承的类叫超类(superclass),继承超类的类叫子类(subclass). 举例说明: 1 class Box 2 { 3 public double width; 4 public double height; 5 public double depth; 6 7 //重载构造方法 8 public Box(Box ob) 9 { 10 width = ob.width; 11 height = ob.height; 12 depth = ob.dep

《Python基础教程(第二版)》学习笔记 -&gt; 第九章 魔法方法、属性和迭代器

准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here 在这两个类中,NewStyle是新式的类,OldStyle是旧式的类,如果文件以__metaclass__ = type 开始,那么两个类都是新式类. 构造方法 构造方法,当一个对象被创建后,会立即调用构造方法.Python中创建一个构造方法,只要把init方法的名字从简单的init修改成__init__

C++学习笔记13-类继承

1.  类模板的 static 成员[不同于C#中的static] 类模板可以像任意其他类一样声明static 成员.以下代码: template <classT> class Foo { public: static std::size_tcount() { return ctr; } // other interfacemembers private: static std::size_tctr; // otherimplementation members }; 定义了名为Foo 的类模