OC—对封装、继承、多态的理解

一、封装

理解封装
将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。


对一个类或对象实现良好的封装,可以实现以下目的

  • 隐藏类的实现细节
  • 让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑,限制对成员变量的不合理访问
  • 可进行数据检查,从而有利于保证对象信息的完整性
  • 便于修改,提高代码的可维护性

访问控制符
Objective-C提供了4个访问控制符:@private、@package、@protected 和 @public。访问控制符用于控制类的成员变量是否可以被其他类访问

  • @private(当前类访问权限):成员变量只能在当前类的内部访问,在类实现部分定义的成员变量相当于默认使用了这种访问权限。
  • @package(同映像访问权限):成员变量可以在当前类以及当前类实现的同一映像中使用(同一映像就是编译后生成的同一框架或同一个执行文件)。这个访问控制符用于部分隐藏成员变量。
  • @protected(子类访问权限):成员变量可以在当前类、当前类的子类的任何地方访问。这个访问限制符用于部分暴露成员变量。在类接口部分定义的成员变量默认是这种访问权限。
  • @public(公共访问权限):成员可以在任意地方访问。

二、继承

特点

  • 继承可以实现代码的复用,减少代码冗杂。
  • Objective-C中每个子类只有一个直接父类。
  • 实现继承的类称为子类,被继承的类称为父类、基类、超类
  • 子类可继承父类的全部成员变量全部方法(包括初始化方法)
@interface Subclass : SuperClass
{   
     //成员变量定义
}
//方法定义
@end

重写父类的方法

  • 重写父类方法时,子类接口部分不需要重新声明要重写的方法,只要在类实现部分直接重写该方法即可。
  • 方法的重写必须注意方法签名关键字要完全相同,即方法名和方法签名中的形参标签都需要完全相同,否则不能算方法重写。
  • 方法重写也可以称为方法覆盖。(可以说子类重写了父类的方法,也可以说子类覆盖了父类的方法)

super关键字
super是Objective-C提供的一个关键字,如果需要在子类方法中调用父类被覆盖的方法,使用super关键字来调父类被覆盖的方法。super用于限定该对象调用它从父类继承得到的属性或方法。


三、多态

理解多态

多态,即对于不同对象响应同一个方法时做出的不同反应

Objective-C指针类型的变量有两个:编译时类型运行时类型。编译时类型由声明该变量时所下使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型与运行时类型不一致,就有可能出现所谓的多态。


实现多态的前提

  • 有继承关系
  • 方法重写
  • 父类指针指向子类对象

id类型
OC中提供了一个id类型,id类型的变量可被赋值给任意类型的指针变量,id类型的变量可以调用该变量实际所指对象的方法。 当通过id类型变量来调用方法时,OC将会执行动态绑定动态绑定,是指oc将会跟踪对象所属类,它会在运行时判断该对象所属类,并在运行时确定需要动态调用的方法,而不是在编译时确定要调用的方法。


定义一个FKBase类,该FKBase类的接口部分如下:

#import <Foundation/Foundation.h>
@interface FKBase : NSObject
- (void) base;
- (void) test;
@end

FKBase类实现部分如下:

@implementation FKBase
- (void) base {
	NSLog(@"父类的普通base方法")}
- (void) test {
	NSLog(@"父类的将!被覆盖的test方法");
}
@end

定义一个FKBase的子类FKSubclass,该子类将会覆盖父类中定义的test方法
接口部分如下:

#import <Foundation/Foundation.h>
#import "FKBase.h"
@interface FKSubclass : FKBase
- (void) sub;
- @end

FKSubclass实现部分如下:

#import <foundation/Foundation.h>
#import "FKSubclass.h"
@implementation FKSubclass
- (void) test {   	   //重写父类test方法
	NSLog(@"子类的覆盖父类的test方法")}
- (void) sub {
	NSLog(@"子类的sub方法");
}
@end

程序如下:

#import <Foundation/Foundation.h>
#import "FKSubclass.h"
int main(int argc, char * argv[]) {
	@autoreleasepool {
		//下面编译时类型和运行时类型一样,不存在多态
		FKBase* bc = [[FKBase alloc] init];
		//下面两行调用FKBase的方法
		[bc base];
		[bc test];
		//下面编译时类型与运行时类型一样,不存在多态
		FKSubclass* sc = [[FKSubclass alloc] init];
		//下面调用将执行从父类继承的base方法
		[sc base];
		//下面调用将执行子类重写的test方法
		[sc test];
		//下面调用执行子类定义的sub方法
		[sc sub];
		//下面编译时类型与运行时类型不一样,发生多态
		FKBase* ploymophicBc = [[FKSubclass alloc] init];
		//下面调用将执行从父类继承到的base方法
		[ploymophicBc base];
		//下面调用将执行子类重写的test方法
		[ploymophicBc test];
		//[ploymophicBc sub] 编译时会出错
		//因为ploymophicBc的编译类型是FKBase,FKBase类没有提供sub方法,所以编译会出错
		id dyna = ploymophicBc;
		[dyna sub];
	}
}

该程序中指针变量ploymophicBc编译时类型是FKBase运行时类型时FKSubclass,当该指针变量调用test方法时(FKBase类中定义了该方法,FKSubclass子类重写了父类该方法),实际上执行的是FKSubclass类中覆盖后的test方法,这就可能出现多态。

猜你喜欢

转载自blog.csdn.net/qq_45836906/article/details/106723837
今日推荐