面向对象编程的基础知识
1. OOP 面向对象编程(Object-Oriented Programming), Cocoa基于OOP概念,Objective-C是一种面向对象的语言。OOP是一种编程架构,可构建由多个对象组成的软件。
1.1 间接--①在代码中通过指针间接获取某个值,而不是直接获取。②让他人代替你自己去完成工作。在编程时,可以在多层之间使用间接。
1.1.1 基本变量就是间接的一种实际应用。
1.1.2 使用文件名的间接
注意:/tmp是Unix临时目录,在计算机重启时会被清空。可以使用/tmp来暂时存放会用到但不必一直保存的临时文件。在真实程序中,永久存放文件的位置有主目录。
了解一下main.m文件
int main(int argc, char * argv[]) {
// 自动释放池
@autoreleasepool {
NSLog(@"argc:%d argv[0]:%s", argc, argv[0]);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
在编程中,我们可以通过main()的argc参数得知启动参数的数量,因为程序名总是用作启动参数而传递,所以argc的值至少是1. 由以上打印可知,argv[0]是程序名。所以,argc是字符数组argv的长度值。可以用xcode修改启动参数。间接的本质:它告诉我们从哪里获得需要的数据。
1.2在面向对象编程中使用间接
间接是OOP的核心。OOP使用间接来获取数据。OOP真正的革命性在于它使用间接来调用代码。
1.2.1 过程式编程
面向过程编程的语言有C、BASIC、Tel和Perl。在过程式编程中,数据通常保存在简单的结构体中(例如C语言的struct元素)。还有一些较为复杂的数据结构,例如链表和树。当调用一个函数时,你将数据传递给函数,函数会处理这些数据。在过程式编程中经常会用到函数:你决定使用什么函数,然后调用它并传递其所需的数据。
注意: 1. C语言的结构体可以相互嵌套。
2.结构体需要分配空间来进行初始化。
3.声明结构体变量时,你可一次性地初始化结构体的所有元素。结构体中的元素按照声明的顺序取值。利用这个小技巧,可以减少程序中要输入的字符量,并且不会影响可读性。
4.使用C语言的联合体(union)来覆盖相同结构体中不同的数据布局。
过程式编程的缺陷:程序的可扩展性很低。
1.2.2 实现面向对象编程
过程式编程建立在函数之上,数据为函数服务,而面向对象编程则以程序的数据为中心,函数为数据服务。在OOP中,不再重点关注程序中的函数,而是关注于数据。在OOP中,数据通过间接方式引用代码,代码可以对数据进行操作。
在OC中,id是一种泛型,可以用来引用任何类型的对象。对象是一种包含代码的struct结构体, 因此id实际上是一个指向结构体的指针。
OC中方括号的意义:用于通知某个对象该去做什么。方括号里的第一项是对象,其余部分是对象执行的操作。在OC中,通知对象执行某种操作称为发送消息(有人也称之为“调用方法”)。向对象发送消息后,需要叫做类的幕后助手来协助调用所需的代码。类是一种能够实例化成对象的结构体。类对象具备极大的优势:如果在运行时改变某个类,则该类的所有对象会自动继承这些变化。
对象调用相应方法执行相应代码的过程如下:
1. 查询对象属于那一个类;
2.相应的类查找其代码块,获取相应方法的地址。
3.最后运行相应方法的代码。
面向对象编码的代码可扩展性、可维护性更高。
1.3 相关术语
类(class):是一种表示对象类型的结构体。对象通过它的类来获取自身的各种信息,尤其是执行每个操作需要运行的代码。建议开发人员在用OC编程时采用首字母大写的类名。
对象(object):是一种包含值和指向其类的隐藏指针的结构体。指向对象的变量通常不需要首字母大写。
实例(instance): 是“对象”的另一种称呼。
消息(message):是对象可以执行的操作,用于通知对象去做什么。
方法(method):是为响应消息而运行的代码。根据对象的类,消息可以调用不同的方法。
方法调度(method dispatcher)是OC使用的一种机制,用于推测执行什么方法以相应某个特定的消息。
接口(interface): 是类为对象提供的特性描述。
实现(implementation):是使接口能正常工作的代码。
1.4 OC语言中的OOP
1.4.1 @interface部分
创建某个特定的类的对象之前,Objective-C编译器需要一些有关该类的信息,尤其是对象的数据成员(即对象的C语言类型结构体应该是什么样子)及其提供的功能。可以使用@interface指令把这些信息传递给编译器。在Objective-C中只要看到@符号,就可以把它看成是对C语言的扩展。 在.h文件中,一般有类的实例变量和方法声明。方法声明列出了每个方法的名称、方法返回值的类型和某些参数。方法声明中的短线表明这是Objective-C方法的声明。这是区分函数原型与方法声明的一种方式,函数原型中没有先行短线。Objective-C中使用void表示无返回值。Objective-C方法可以返回与C函数相同的类型:标准类型(整型、浮点型和字符串)、指针、引用对象和结构体。OC中有一种名叫中缀符的语法技术。即:方法的名称及其参数都是合在一起的。例如[circle setFillColor:kRedColor]。方法的名称是setFillColor:, 结尾处的冒号是名称的一部分,它告诉编译器和编程人员后面会出现参数。紧跟冒号其后的是参数类型和参数名。你可以在方法的主体中使用该名称引用参数。为了增强代码的可读性,可以选择有意义的参数名称。如果方法使用参数,则需要冒号,否则不需要冒号。@end告诉编译器,我们已经完成对某个类的声明。一般建议在所有的@end语句后添加注释来注明类的名称。
1.4.2 @implementation部分
@interface用于定义类的公共接口。通常,接口被称为API,而真正使对象能够运行的代码位于@implementation部分中。@implementation是一个编译器指令,表明你将为某个类提供代码。类名出现在@implementation之后。该行的结尾处没有分号,因为在OC编译器指令后不必使用分号。对于.m文件中各个方法的定义,它们不必按照在@interface指令中的顺序出现。你甚至可以在@implementation中定义那些在@interface中没有声明过的方法。你可以把它们看做是仅能在当前类实现中使用的私有方法。尽管可以这样,但不是绝对不能从该实现之外访问该方法。OC中不存在真正的私有方法,也无法把某个方法标识为私有方法,从而禁止其他代码调用它。这是OC动态本质的副作用。@interface和@implementation间的参数名不同是允许的。例如:.h文件中 -(void)setFillColor:(UIColor *)fillColor,而.m文件中-(void)setFillColor:(UIColor *)c。 即:如果实例变量的名称和参数名的名称相同,编译器会组织我们访问该实例变量,即参数名会覆盖掉初始变量,为参数名取一个新的名称,或者修改实例变量名称都可以避免这类问题。在OC中调用方法时,一个名为self的秘密隐藏参数将被传递给接收对象,而这个参数引用的就是该接收对象。传递隐藏的参数是间接操作的一个实例。因为OC运行时(runtime)可以将不同的对象当成隐藏的self参数传递,所以那些对象的实例变量发生更改时,运行时也可以进行相应的更改。OC运行时是指用户运行应用程序时,支持这些应用程序的代码块。运行时负责执行非常重要的任务,如向对象发送消息和传递参数。
1.4.3 实例化对象
创建对象的过程叫做实例化。实例化对象时,需要分配内存,然后将这 些内存初始化并保存为有用的默认值,这些值不同于通过新分配的内存获得的随机值(注:对象的内存地址是计算机随机分配的)。内存分配和初始化工作完成之后,就意味着新的实例对象实例已经创建好了。由于对象的局部变量只在对象的实例中有效,因此我们称它们为实例变量。为了创建一个新的对象,我们需要向相应的类发送new消息。该类接收并处理完new消息后,我们就会得到一个可以使用的新对象实例。
OC具有一个极好的特性,你可以把类当成对象发送消息。对于那些不局限于某个特定的对象而对全体类都通用的操作来说,这非常便捷。最好的例子就是给新对象分配空间。继承,可以有效避免冗余代码。面向对象编程的实用优势:可扩展性很强。OC中每个方法调用都包括一个名为self的隐藏参数,它是对象自身。使用self参数后,方法可以查找并操作对象的数据。方法的实现和对象数据的模板是由对象的类定义的。
面向对象编程的开放/关闭原则:即软件实体应该对扩展开放,而对修改关闭。应对变化时,遵循开放/关闭原则的软件会更加坚实耐用,因为你不必修改那些可正常运行的代码。
OC中self和super的理解:self是类的隐藏参数,指向当前调用方法的类对象(方法的接收者)实例,而super本质是一个编译器标识符。两者的不同之处在于:super会告诉编译器,去父类的方法列表里面找。在同一个类中,调用[self class]和[super class],消息的接收者都是当前类对象(self class)所对应的实例。当使用self调用类方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用super调用类方法时,则从父类的方法列表中开始找,然后调用父类的这个方法。
网友评论