您的位置:首页 > 移动开发 > Objective-C

Object-C基础(7)——类与对象

2016-03-27 20:52 435 查看
Object-C的面向对象

类:一批具有相同特征的对象的统称(一批相似对象的概念)

类:一批对象的总称。

对象:具体存在的东西。

定义类的语法:

Object-C定义类,需要2个部分:

头文件部分(声明部分) —— 相当表盘部分,暴露出来供用户操作的。

@interface <类名> :NSObject

{

成员变量

}

方法声明

@end

类名:只要是一个标识符即可。但从程序可读性的角度来看,类名必须是由一个或多个有意义的单词连缀而言。

成员变量:用于描述该类或该类的对象所具有的状态信息。程序只记录与业务相关的状态信息。

语法:<类型> <变量名>;

方法:用于描述该类或该类的对象所具有的行为。程序只记录与业务相关的行为。

方法语法:

+|- (返回值类型) 方法名: (形参类型1) 形参名1 形参标签2: (形参类型2) 形参名2 形参标签3: (形参类型3) 形参名3 ...

+表明该方法属于类本身,该方法只能由类来调用;-表明该方法属于该类的对象,因此只能由于对象调用。

返回值类型,可以是任意有效的类型。

方法名,只要是一个有效的标示符即可。但从程序可读性角度来看,方法名应该是一个或多个单词连缀而言,最好方法名是动词。

形参列表:除了第一个形参之外,后面每个形参都需要3个部分:形参标签: (形参类型) 形参名

实现部分 —— 相当于表体部分,被彻底隐藏的,但负责提供表盘部分的显示。

@implementation <类名>

{

成员变量 —— 此处定义的成员变量,相当于被隐藏的成员变量。

}

实现接口部分定义的所有方法。

额外定义实现部分的方法。—— 此处额外定义的方法,相当于是被隐藏的方法,因此不能被调用。

@end

类的作用:

1. 定义变量。所有类,都属于指针类型。

2. 创建对象。

3. 调用类方法。

4. 用于被继承、派生子类。

【不存在的】: 可以访问类变量 ———— 但不存在。Object-C的类不能定义类变量。

创建对象

[[类名 alloc] init]

init,包括后面的系列initWithXxx方法,被称为初始化方法。

[类名 new] - 很少使用。

对象的作用:

1. 调用实例方法

2. 访问实例变量

对象变量 -> 成员变量

调用方法

[类|对象 方法:参数1 形参标签2: 参数2 形参标签3: 参数3...];

对象与指针

用自定义类来声明变量时,都需要在类名后添加一个*,表明这是一个指针。

指针:意味着,当程序把一个对象赋值给指针变量时,实际上只是把该对象的首地址存入指针变量,并未真正把对象存入指针中。

同一个对象,可以被很多个指针变量(引用变量)指向(引用)它。

反过来:供一个指针变量,最多只能指向一个对象。

对象 —— 只是赋值,不会创建对象。要看到allocate(分配内存)才会创建对象。

dealloc —— 删除内存,销毁该对象。

self 关键字 代表了调用方法的调用者。通俗来说,谁调用方法,self就代表谁。

如果在实例方法中,总是由实例调用,因此self总是代表调用该方法的对象;

如果在类方法中,总是由类调用,因此self总是代表调用该方法的类本身。

self,主要是作为一个代词。 当它出现在任何方法中,谁调用该方法,self就代表了谁。

id类型

C/Object-C都是强类型的语言,指定的类型的变量,只能接受指定类型的对象。

但id不同,它可以接受任意类型的对象。

对于id类型的变量而言,它可以在运行时动态解析、绑定要调用的方法。

需要说明都是,动态绑定,必须绑定的是实际存在的方法——否则一样会编译出错。

只有方法才会执行动态绑定,即使成员变量是id类型,成员变量也不会执行动态绑定。

【注意:】如果程序对id类型的指针变量的成员变量进行赋值,程序会编译报错。方法详解:

理解方法:

1. 方法和函数的本质是一样的。

2. 定义方法时,方法不能独立存在,必须定义在类里面。有的方法(+)属于类;有的方法(-)属于实例(对象)

3. 调用方法时,方法也必须有调用者 —— 调用者被称为主调(主语、调用者)

对于+方法,调用者必须是类本身。对于-方法,调用者必须是实例。

猪八戒吃西瓜

[猪八戒 吃:西瓜];

猪八戒.吃(西瓜);

形参个数可变的方法

调用该方法时,可以为该参数传入多个值。

声明方法时,需要使用 ,... 形式来声明个数可变的形参。

实现方法时,需要利用如下来获取调用方法时传入的多个参数:

va_list:这相当于一个指针类型。

va_start: 它是一个函数。va_start(va_list类型变量 , 个数可变的形参名);

va_arg: 它也是一个函数,每次获取一个参数值。

va_end:处理完成后,就使用该函数来关闭va_list类型的变量。

#import "FKComputer.h"

@implementation FKComputer

- (void) print: (NSString*) content , ...
{
// 定义一个va_list类型的变量,用于获取程序传入的多个个数可变的参数
va_list argList;

// 如果content存在——至少content参数的第一个值要是存在的。
if( content )
{
// 首先处理content参数的第一个值
NSLog(@"%@" , content);
// 将content参数的参数列表绑定给argList
va_start(argList , content);

// 程序每调用va_arg一次,即可获取一个参数值。
NSString* arg = va_arg(argList , id);
// 如果arg不为nil,就处理该参数——但如果最后一次取出的是nil,循环结束。
while( arg )
{
NSLog(@"%@" , arg);
arg = va_arg(argList , id);
}

va_end(argList); // 结束处理。
}

}

@end


注意:

1. 个数可变的形参只能作为方法的最后一个形参,因此一个方法最多只能声明一个个数可变的形参。

2. 调用个数可变的形参的方法时,程序至少要为个数可变的形参传入一个参数。

变量

全局变量:在源文件范围内声明(不再任何花括号中)。

直接保存在静态存储区的,程序退出时,全局变量才会死亡。

系统会为全局变量自动分配初始值。初始值为广义的0。

局部变量:在函数或方法中声明的。

保存当前的方法或函数栈的,因此随着方法或函数的结束而死亡。

局部变量在程序显式赋初始值之前,局部变量的值是不确定。

成员变量(实例变量):在类后面(接口或实现部分)的一对花括号中。

成员变量会随着对象的allocate而分配内存,成员变量开始出现。

随着对象被回收,成员变量才会被销毁。

实例变量,随着实例的生而生;随着实例的死而死。

——在ARC机制下,如果一个对象没有任何引用变量指向它,那么该对象就会被销毁。

系统会为成员变量自动分配初始值。初始值为广义的0(0、0.0、nil)

实质上,创建对象时,alloc负责分配内存; init就负责执行默认的初始化。

生命期限:

局部变量 < 成员变量 < 全局变量

Object-C所有的成员变量都是实例变量,因此OC只有实例变量,没有类变量。

模拟类变量

用一个static全局变量可模拟类变量。

static全局变量 —— 只能在当前源文件中被访问的全局变量,内部全局变量。

步骤:

(1)在类的实现部分定义一个static全局变量。

(2)为该类声明、并实现一组getter和setter的类方法,用于操作该static全局变量

其中getter方法用于获取全局变量的值;setter方法用于修改全局变量的值。

封装

面向对象的3大特征: 封装、继承、多态。

封装:无处不在。封装包括2方面的含义:

- 把对象的实现细节隐藏在内部。 合理隐藏。

- 把供用户操作的interface暴露出来。 合理暴露。

Object-C实现封装的方式:

通过访问控制符。

↗ @package ↘

@private @public

↘ @protected ↗

@private:彻底隐藏的访问控制符。被@private控制的成员变量,只能在当前类中被访问。 (彻底隐藏)

@package:被@package控制的成员变量,只能在当前类和当前类的同一个映像中被访问。 (部分隐藏:在同一个映像内不隐藏)

@protected:被@protected控制的成员变量,只能在当前类和当前类的所有子类中被访问。 (部分暴露)

@public:被@public控制的成员变量,可以在任意地方被访问。 (彻底暴露)

当前类 与当前类的同一个镜像 当前类的子类 全部范围

@private √ × × ×

@package √ √ × ×

@protected √ × √ ×

@public √ √ √ √

如果成员变量没有使用访问控制符,默认使用@protected修饰。

Object-C的权限控制符,是从当前权限控制符开始,一直管到下一个权限控制符。

一般来说,设计一个类时,推荐做法是:

(1)将成员变量使用private隐藏起来,避免程序直接访问该成员变量。

(2)为该成员变量提供setter、getter方法,setter、getter方法就可添加控制访问逻辑,

从而避免直接修改对象的成员变量的值造成的破坏。

对于方法而言,不能使用@private、@protected、@package、@public控制。

所有在接口部分声明过的方法,都是暴露的方法(相当于public)。

如果只在实现部分实现、未在接口部分声明的方法,都是私有方法(相当于private)。

关于@package的理解

1. 被@package的成员,肯定可以在当前类中被访问。

2. 同一个镜像。 只要和当前类编译成一个文件(包括同一个可执行文件、同一个库文件等),即可称为同一个镜像。

以后在开发APP时,可以只是简单地将成员声明为@package。

合成getter、setter方法

(1)用@property来声明属性。

@property (指示符)NSString* brand;

一条property定义,可以得到3个东西:

(1)得到一个在属性名前面添加_前缀的成员变量——这是成员变量,也是被彻底隐藏的。

(2)getter方法。

(3)setter方法。

如果我们认为系统实现的getter、setter方法不好,程序也可在实现部分重新实现setter、setter方法。

(2) 可选的。如果你希望改变@property合成属性所对应的成员变量名,才需要在实现部分使用@synthesize指令。

@synthesize 属性名; —— 让合成属性对应的成员变量名与属性名完全相同。

@synthesize 属性名 = 新名字; —— 让合成属性对应的成员变量名为新名字。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: