------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、基本术语:
1、面向对象编程(OBject - Oriented Programming)的首字母缩写为OOP。OOP是一种变成架构,可构建由多个对象组成的软件。
2、类(class)是一种表示对象类型的结构体。对象通过它的类来获取自身的各种信息,尤其是执行每个操作需要运行的代码。
3、对象(object)是一种包含值和指向其类的隐藏指针(isa)的结构体。对象有另一种称呼“实例(instance)”。
4、消息(message)是对象可以执行的操作,用于通知对象取做什么。对象接受消息后,将查询相应的类,以便找到正确的代码来运行。(发送消息 == 调用方法)
5、方法(method)是为了相应消息而运行的代码,根据对象的类,消息可以调用不同的方法。
6、方法调度(method dispatcher)是OC使用的一种机制,用于推测执行什么方法以相应特定的消息。
7、接口(interface)是类为对象提供的特性描述。
8、实现(implementation)是使接口能正常工作的代码。
二、类
1、OC中每个类都由两部分构成:接口和实现
接口:创建对象前,OC编译器需要一些有关该类的信息,尤其是对象的数据成员及其提供的功能,使用@interface指令把这些消息传递给编译器。
格式
@interface 类名 : 父类
{
成员变量们
}
方法们
@end//Car
一下是一个Car类的接口:
//:NSObject 继承NSObject类,让Car类具有NSObject类的方法。
@interface Car : NSObject
{
//属性(成员变量/实例变量) 写在大括号里面
int _wheels;
double _speed;
}
//行为(方法)
- (void)run:(double)speed;
@end
@interface 行中的NSObject告诉编译器,Car类是基于NSObject类的。该语表明每一个Car类都是一个NSObject,并且每个Car类都将继承NSObject类定义的所有行为(方法)。
{}大括号中表示创建的新对象有2个元素构成,每个Car对象都将有自己的_wheel和_speed。_wheel和_speed的值称为Car类的实例变量(成员变量)。
大括号外的 - (void)run:(double)speed;有点像C语言中的函数声明。在OC中,它们称为方法声明。方法声明列出了每个方法的名称、返回值的类型和某些参数。
最前面的减号 - 表明这个方法是一个对象方法。减号后面是方法的返回值类型,位于小括号中。run:是方法名注意,run后面的冒号是方法名的一部分,他告诉编译器和其他人后面会出现参数。在后面是参数类型,也位于小括号中。最后的speed是参数名。
注意“冒号”是方法名称非常重要的组成部分。
- (void) run;和- (void)run:(double)speed;两个方法是不同的。如果方法使用参数,则需要冒号,不适用参数则不需要冒号。
最后一行的@end告诉编译器,我们已经完成了Car类的声明。
建议:在每个@end语句后面添加注释来注明类的名称。
以上就是完整的Car类的借口。
实现:能使对象运行的代码位于@implementation中。
//实现
@implementation Car
- (void)run:(double)speed
{
NSLog(@"汽车以%f公里/小时的速度奔跑",speed);
}
@end
@implementation是一个编译器指令,表示你将为某个类提供代码。类名出现在@implementation之后。
接下来是方法编译,这里只有一个方法,如果有多个方法时它们不必按照@interface指令中的顺序出现。甚至可以在@implementation中定义没有在@interface中声明过的方法。你可以把他们看做仅能在当前类视线中使用的私有方法。(OC中不存在真正的私有方法,也无法把某个方法标示为私有方法,从而禁止其他代码调用它。这是OC动态本质的副作用。)
- (void)run:(double)speed
{
NSLog(@"汽车以%f公里/小时的速度奔跑",speed);
}
方法定义的第一行看上去与@interface部分的声明非常类似,区别是结尾处有没有分号。
大括号内部的就是方法实现的代码。
最后类的实现也是以@end结尾的。
以上一个完整的类就建立完成了。
类名的规范:
1、类名第一个字母必须大写
2、不能有下划线
3、如果有多个英文单词,使用驼峰标示,每个单子的首字母都大写。
实例化对象
最后,是一个非常关键的过程,创建一个有多个轮子和行驶速度的小汽车,这个过程作业点说叫做实例化(instantiation)。
实例化对象时,需要分配内存,然后将内存中存放的成员变量初始化并保存为有用的默认值,默认为0。初始化完成后,意味着新的对象实例已经创建好了。对象的局部变量只在对象的实例中有效,因此成为实例变量,通常简称ivar。
<span style="font-size:18px;">Car *car = [Car new];//等号右边返回值是新建的对象的地址。把返回的地址赋值给一个Car类型的指针变量。
//加上@public后方可使用指针直接操作成员变量。
car -> _speed = 250;
car -> _wheels = 3;
//给car所指向的对象发送一条run消息,告诉Car对象调用run方法。
[car run:23.4];</span>
为了创建一个对象,我们需要想相应的类发送new消息。该类接受并处理完new消息后,我们就会得到一个可以使用的新的对象实例。
这里我们使用指针直接操作对象的实例变量,前提是在声明中,在需要直接操作的实例变量前加上@public。否则无法直接通过指针操作实例变量。
<span style="font-size:18px;">car -> _speed = 250;
car -> _wheels = 3;</span>
同结构体指针类似,使用->可以直接修改或访问对象中的变量。
<span style="font-size:18px;">[car run:23.4];</span>
给car指向的对象发送run消息,调用run方法。方法的参数值是23.4。
最后运行结果是:汽车以23.400000公里/小时的速度奔跑。
以上一个类和对象就此创建完成。
最后,类、对象和内存。
在运行中,不光对象在内存中占据存储空间,类在内存中也占据存储空间。
当第一次使用[Car new]前,它会把类加载进内存。最先先给类分配快存储空间,然后创建一个Person对象。给对象分配存储空间。
类内存中只存储类的方法列表(方法声明)
每个对象内部默认都有个isa指针,这个指针就指向所对应的类。
当调用方法时,当执行[car run:11]时,会给car所指向的对象发送一条run消息,对象会顺着isa指针在内存中找到对应的Car类。在类里面的方法列表中找对应的方法。如果找到,就执行run方法对应的实现。如果找不到就会报错。