OC继承详解与使用规则

1、OC中如果类A继承类B,B就成为A的父类。那么B的成员全部属于A的成员。相当于A全部拥有了B的所有成员(所有变量与所有方法)。即子类拥有父类中所有的成员变量和方法。

2、继承的使用场合:

(1)如果有两个或者两个以上的类含有很多相同的成分(成员变量/方法相同)。那么就可以把它们相同的部分提取到一个单独的类中,让这些相似的类继承于它。继承的实质就是把多个类中相同的代码抽出来放到一个单独的类中,然后让这些多个类继承于它。

(2)当A类拥有B类中的部分属性和方法时,可以考虑让B类继承A类。

(3)当B是A的一种时,用继承,即B继承A。当B拥有A,A是B的一个组成部分时。继承是一种,即种类的关系;而组合是一部分,即拥有的关系。即当XXX是XX时用继承,当XXX拥有XX时用组合。

3、继承的好处:抽取重复的代码。建立了类之间的关系。

4、父类中必须继承自NSObject类,如果不继承这个类 任何类都没有创建对象的能力。当父类继承了NSObject,子类直接继承父类即可,相当于间接的继承了NSObject。(基本上所有的类都继承自NSObject根类,还有一根类NSProxy但基本上用不着)。

5、在OC类的继承中,直接继承NSObject的基类内部会有被加载进来的NSObject类指针(Superclass地址),即这个基类Superclass指针的值指向被加载进来的NSObject类所在内存的首地址。然后直接继承自这个基类的子类中会有它直接继承的父类的地址即Superclass,也就是这个基类的地址。也就是说每一个类都有一个Superclass指针指向它直接继承的父类(NSObject类或别的类),而每一个对象内部都有一个isa指针(指向直接创建这个对象的类),即由哪个类创建的这个对象那么这个对象内部的isa的值就是哪个类所占内存的首地址。(切记:如果这个类是根类例如NSObject,那么这个类的Superclass的值为NULL)。

注意:在首次用类创建对象时,切记是首次。即第一次用:[类名 alloc/new]来创建对象时会把这个类加载进内存。每个类只加载一次。即同一个类所创建的每个对象内部的isa指针都是相同的,都指向这个类。

6、在OC中,所谓的继承程单链继承,即单一继承。

7、id可以代替所有对象指针,id就是泛型。id在使用时也利用了动态绑定的原理。id在编译时是无法确定的,在将对象指针赋给id类型的变量后,利用id类型的变量调用方法时,id类型的变量会根据对象保存的isa指针(创建此对象的类的地址)来找到相应的方法列表进行调用。

8、OC中不允许子类和父类拥有相同名称的成员变量。但是方法可以相同(即重写:子类重新实现父类中的某个方法)。重写的好处是:覆盖父类以前的所有行为;

9、向上查找规则:当一个类的对象在调用方法的过程中,先从自身开始查找,如果自身的类中没有亲自实现的话就从父类中进行查找,如果父类中没有的话就一直向上查找。如果找到根类仍然没有的话就会报错。切记:优先查找自身的部分,没有的话再向上查找。这个过程是不可逆的。

10、在类的对象成员方法(实例方法)中不能用self来调用类方法(自身的不行,父类的更不行),同样类方法中也不能用self来调用实例方法(包括父类的)。概括为:类方法中只能调用类方法,对象方法中只能调用对象方法,在外部 类方法只能由类名调用,对象方法只能由对象调用。OC的特点就是界限很清楚,当用类名调用类方法时,或在类方法中用self调用了别的类方法,先从自身的类方法查找,如果有的话就直接调用 自身找不到时就从父类的静态方法中查找(还是向上查找的原则)。当用对象调用实例方法时也与此类似,不同的是当在自身的实例方法中找不到时,开始向上查找实例方法。

11、在同一个文件中如main.m 实现父类和子类的声明和实现时,必须将父类的声明写在子类声明的前面,与父类的实现和子类的实现的先后顺序无关。

12、继承的缺点:耦合性太强了,就是有继承关系的两个类之间联系过于紧密。当一个类出现变动/故障时,继承它的类也会崩溃。

13、继承常用的关键字super:

(1)super用来调用父类方法;当子类中重写了父类方法,如果想在这个子类方法中完全实现父类被重写方法的内容,就需要用super来调用被覆盖的父类版本的成员方法。(如果用self来调用这个方法,由于系统优先在自身查找的原因,等于是自己调用自己,会陷入死循环)。

(2)super不仅可以调用父类对象方法,也可以调用父类的类方法。但与self类似的是,子类对象方法中只能用super调用父类的对象方法。子类的类方法中只能用super调用父类的类方法。无论用哪种调用方式,对象方法中只能调用对象方法,类方法中只能调用类方法;无论哪种调用方式都遵循从自身开始向上查找的原则。

(3) 所以如果super在对象方法中就会调用父类的对象/实例方法,如果super在类方法中就会调用父类中的类方法。

注意:super的使用场合,一般当子类想在父类方法的基础之上做些延伸进而重写父类方法时需要把父类方法的实现内容拿过来,就要用super调用被覆盖的父类方法。

14、已知所有的OC类的初始化成员的方法有三个要点:(一)基本都是id类型,(二)必须返回self值,(三)必须调用父类的初始化方法来初始化从父类继承而来的成员。但是第三条具体实现可能有所不同,实现直接继承NSObject的类的构造方法中,直接用if(self=[super init]){ //初始化自身扩展的成员 }这是因为NSObject的初始化方法(构造方法)就是init。如果类不直接继承NSObject类,继承自手动实现的类,那么在实现它的构造方法 时就要用以下格式来初始化父类成员:if(self=[super 父类构造方法名:参数1,参数二,...参数n]){ //初始化自身扩展的成员},除非这个手动提供的构造方法重写了NSObject的init方法,在继承这个手动类时才用第一种格式。

15、与C++类似的是在调用子类的dealloc方法时会自动调用父类的dealloc方法来释放子类从父类继承来的部分,所以不需要在子类的dealloc方法中调用父类的dealloc方法。这与组合类不同,组合类中的对象指针成员必须在类的dealloc方法中release一次。仍然遵循“ 谁创建,谁释放”的原则。

代码实现,实例如下:

代码要求
1、 定义一个轮胎类Tair,要求如下:a、实例变量:int screws; double radius; b、实例方法:
初始化方法:要对两个变量进行初始化 输出方法:print用来输出所有实例变量的值 自己实现set方法:set方法包含两个形参 实现dealloc函数
2、 定义一个汽车类Car,要求如下:
c、 实例变量:int seats; double height; float width;Tair *tair; d、实例方法:初始化方法:要对四个变量进行初始化 输出方法:print用来输出所有实例变量的值
自己实现实例变量tair的set方法:set方法要求用retain模式。 实现dealloc函数
3、 定义一个轿车类SaloonCar,它继承于Car类。要求如下
a、 实例变量:int windows; b、实例方法:
初始化方法:要对五个变量进行初始化
输出方法:print用来输出所有实例变量的值
实现dealloc函数

编辑Tair.h代码如下:

//
//  Tair.h
//  Test_extend
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Tair : NSObject
{
    int screws;
    double radius;
}
@property int screws;
@property double radius;
-(id)setScrewAndRadius:(int) _screws andRadius:(double) _radius;
-(void) print;
@end

编辑Tair.m代码如下:

//
//  Tair.m
//  Test_extend
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Tair.h"

@implementation Tair
@synthesize radius,screws;
-(id)setScrewAndRadius:(int) _screws andRadius:(double) _radius{
    if(self=[super init]){//super指向NSObject,调用了NSObject的init初始化构造方法
        self .screws=_screws;
        self.radius=_radius;
    }
    return  self;
}
-(void)print{
    NSLog(@"screws= %d   radius=%.2lf",self.screws,self.radius);
}
-(void)dealloc{
    NSLog(@"Invoke Tair Methods");
    [super dealloc];
}
@end
编辑Car.h如下:

//
//  Car.h
//  Test_extend
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Tair.h"
@class Tair;
@interface Car : NSObject
{
    int seats;
    double height;
    float width;
    Tair * tair;
  }
@property int seats;
@property double height;
@property float   width;
@property (nonatomic,retain) Tair * tair;
-(void) print;
-(id) initWithSeats:(int) _seats  andHeight:(double) _height andWidth:(float) _width andTair:(Tair *) _tair;
@end

编辑Car.m如下:

//
//  Car.m
//  Test_extend
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Car.h"
@implementation Car
@synthesize height,seats,width,tair;
-(void) print{
    NSLog(@"height=%.2lf width=%.2f seats=%d",self.height,self.width,self.seats);
    [tair print];
}
-(id) initWithSeats:(int) _seats  andHeight:(double) _height andWidth:(float) _width andTair:(Tair *) _tair{
    if(self=[super init]){
        self.seats=_seats;//利用self自身指针,调用了已经实现的setter方法进行赋值初始化
        self.height=_height;
        self.width=_width;
        self.tair=_tair;
    }
    return self;
}
-(void)dealloc{
    [tair release]; //释放自身扩展的成员,因为tair是类自身的成员部分。所以要由类自己的daealloc方法内进行释放,还是那句话“谁创建,谁释放”
    NSLog(@"Invoke Car");
    [super dealloc];//调用父类NSObject的dealloc方法,释放从父类继承来的部分
}
@end
编辑SalloonCar.h如下:

//
//  SaloonCar.h
//  Test_extend
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Car.h"
@class Car;
@interface SaloonCar : Car
{
    int windows;
}
-(id)initWithSeats:(int)_seats andHeight:(double)_height andWidth:(float)_width andTair:(Tair *)_tair andWin:(int) _windows;
-(void)print;
@end

编辑SalloonCar.m如下:

//
//  SaloonCar.m
//  Test_extend
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "SaloonCar.h"
@implementation SaloonCar
-(id)initWithSeats:(int)_seats andHeight:(double)_height andWidth:(float)_width andTair:(Tair *)_tair andWin:(int) _windows{
    if (self=[super initWithSeats:_seats andHeight:_height andWidth:_width andTair:_tair]) {//调用父类(Car)初始化方法初始化从父类继承而来的成员
        windows=_windows;
    }
    return self;
}
-(void)print{//重写父类的方法,扩展父类。在父类实现的基础上增添新内容
    [super print];//利用super调用被覆盖的父类print方法
    NSLog(@"windows=%d",windows);//增添自己新特性
}
-(void)dealloc{//重写dealloc方法
    NSLog(@"SaloonCar Invoke");
    [super dealloc];//调用父类(Car)的dealloc方法,释放自身从父类继承来的部分
}
@end

编辑main.m如下:

//
//  main.m
//  Test_extend
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SaloonCar.h"
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        Tair *t=[[Tair alloc] setScrewAndRadius:12 andRadius:35.4];
        [t print];
        Car *c=[[Car alloc] initWithSeats:100 andHeight:245.3 andWidth:23.3 andTair:t];
        [c setTair:t];
        [c print];
        SaloonCar *s=[[SaloonCar alloc]  initWithSeats:100 andHeight:251.23 andWidth:25.3 andTair:t andWin:600];
        [s print];
        [s release];
        [t release];
        [c release];
    }
    return 0;
}

运行结果如下:





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值