1.综述
面向过程(ProcedureOriented)就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象(ObjectOriented,简称OO)是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
面向过程关注的是解决问题需要哪些步骤;面向对象关注的是解决问题需要哪些对象。
例如,吃饭。面向过程的解决思路是:选菜,买菜,生火,做饭,吃,面向对象的解决思路是,找到服务员点菜,其它的步骤让服务员去解决。
2.类和对象
(1).类和对象的关系
OC中的类相当于图纸,用来描述一类事物。也就是说,要想创建对象,必须先有类;
OC利用类来创建对象,对象是类的具体存在;
面向对象解决问题应该是先考虑需要设计哪些类,再利用类创建多少个对象;
所以我们可以如下理解,对于建造汽车而言,类就相当与建造汽车所用的图纸,汽车的各个部分的零件(对象)是由图纸(类)实例化生成的,我们的零件都是根据图纸得来的。
如何设计一个类?
对于一个类来说,我们只关心类的名称(类名),累的属性(属性)和类的行为(方法)。
类的声明:
#import
// 类的声明
@interface Car : NSObject
{
@public
int wheels; // 多少个轮子
int speed; // 时速
}
- (void)run; // 跑的行为
@end
成员变量:
@interface的大括号{}中声明的变量:wheels、speed
@interface的大括号和函数的大括号是不一样的
默认会初始化为0
@public可以让Car对象的wheels和speed属性被外界访问
加上:NSObject的目的是让Car类具备创建对象的能力类的实现
// 类的实现
@implementation Car
- (void) run
{
NSLog(@"%i个轮子,%i时速的车子跑起来了", wheels, speed);
}
@end
创建对象
// 主函数
int main()
{
// 创建车子对象
Car *c = [Car new];
c->wheels = 3;
c->speed = 300;
[c run];
return 0;
}
Car *c = [Car new];用一个指针变量c指向内存中的Car对象。
设置车子对象的属性
跟用指向结构体的指针访问结构体属性一样,用->
c->wheels = 3;
c->speed = 300;
Car *c1 = [Car new]; //创建对象
c1->wheels = 4; //对成员变量赋值
Car *c2 = [Car new]; //创建对象
c2->speed = 250;对成员变量赋值
[c1 run];
(2).类的声明和实现
@interface和@implementation的分工,可以用下图表示:
如图所示,@interface(类的声明)@interface就好像暴露在外面的时钟表面,我们可以通过指针知道现在具体的时间; @implementation就好像隐藏在时钟内部的构造实现,为什么指针会指到12点?是因为怀表内部的齿轮通过各种运动而产生的,简而言之,我们可以理解声明为告诉编译器,我们有这些东西,而实现则可以理解为这些东西具体的样子和功能等等。
常见错误如下:
l 只有类的声明,没有类的实现
l 漏了@end
l @interface和@implementation嵌套
l 两个类的声明嵌套
l 成员变量没有写在括号里面
l 方法的声明写在了大括号里面
l 成员变量不能在{}中进行初始化、不能被直接拿出去访问
l 方法不能当做函数一样调用
类的实现可用写在main函数的后面,主要在声明后面就行举例说明:
@interface Car : NSObject
{// 成员变量\实例变量
//int wheels = 4; 不允许在这里初始化
//static int wheels; 不能随便将成员变量当做C语言中的变量来使用
@public
int wheels;
}
- (void)run;
- (void)fly;
@end
@interface Person:NSObject
{
int a;
int b;
- (void)test; //方法定义在{}内部
}
int c; //成员变量定义在{}外面
//缺少@end
(3).类的方法以及与函数的区别
不带参数的方法
// 方法声明
- (double)pi;
// 方法实现
- (double)pi
{
return 3.14;
}
- (void)multWithOne:(int)a; //声明
- (void)multWithOne:(int)a //实现
{
a=a*2;
}
[p multWithOne:10]; //使用
声明 调用
带多个参数的方法
- (void)AddWithOne:(int)a two:(int)b three(int)c; //声明
- (void)AddWithOne:(int)a two:(int)b three(int)c //实现
{
a=a+b+c;
}
[p AddWithOne:1 two:2 three:3];//调用
@interface JiSuanQi : NSObject
// 方法名:pi
- (double)pi;
// OC方法中,一个参数对应一个冒号
// 方法名:pingFang:(冒号也是方法名的一部分)
- (int)pingFang:(int)num;
//- (int)sum:(int)num1 :(int)num2;
// 方法名:sumWithNum1:andNum2:
- (int)sumWithNum1:(int)num1 andNum2:(int)num2;
//- (int)sumWithNum1:(int)num1 andNum2:(int)num2 andNum3:(int)num3;
@end
@implementation JiSuanQi
- (double)pi
{
return 3.14;
}
- (int)pingFang:(int)num
{
return num * num;
}
//- (int)sum:(int)num1 :(int)num2
- (int)sumWithNum1:(int)num1 andNum2:(int)num2
{
return num1 + num2;
}
@end
方法与函数的区别:
方法
1.对象方法都是以减号 -
2.对象方法的声明必须写在@interface和@end之间
对象方法的实现必须写在@implementation和@end之间
3.对象方法只能由对象来调用
4.对象方法归类\对象所有
函数
1.函数能写在文件中的任意位置(@interface和@end之间除外),函数归文件所有
2.函数调用不依赖于对象
3.函数内部不能直接通过成员变量名访问某个对象的成员变量
#import
@interface Person:NSObject
{
int a;
int b;
}
- (void)fly; //方法声明
@end
@implementation Person
- (void)fly
{
NSLog(@"we can fly"); //方法实现
}
@end
//函数
void test()
{
NSLog(@"This is a 函数");
}
int main()
{
Person *p =[Person new];
[p fly]; //方法使用
test();//函数使用
}
(4).封装
@public的成员可以被随意赋值,应该使用set方法和get方法来管理成员的访问(类似机场的安检、水龙头过滤,过滤掉不合理的东西),比如僵尸的生命值不能为负数.
1.set方法
命名规范:
方法都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写
形参名称不要跟成员变量同名
(1)不让数据暴露在外,保证了数据的安全性
(2)对设置的数据进行过滤
2.get方法
作用:返回对象内部的成员变量命名规范:get方法的名称一般就跟成员变量同名
3.成员变量的命名规范
成员变量都以下划线 _ 开头可以跟get方法的名称区分开
可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量。
#import
// 声明
@interface Car : NSObject
{
int _wheels; // 轮子个数
}
/*set方法*/
- (void) setWheels:(int)wheels;
/*get方法*/
- (int) wheels;
@end
@implementation Car
// set方法的实现
- (void) setWheels:(int)wheels
{
// 对外面传进来的轮子数进行过滤
if (wheels<=0)
{
wheels = 1;
}
_wheels = wheels;
}
// get方法的实现
- (int) wheels
{
return _wheels;
}
@end
4.self关键字
Self是一个指针,谁调用了当前方法,self就指向谁。
【出现在对象方法中,就代表着当前对象,出现在类方法中,就代表着当前类】
Self的用途:
(1)可以利用self->成员变量名访问当前对象内部的成员变量(仅在对象方法中)
(2)[self 方法名];可以调用其他的对象方法或者是类方法。