码迷,mamicode.com
首页 > 其他好文 > 详细

objective-c学习笔记(2)

时间:2014-10-19 22:36:20      阅读:271      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   ar   使用   java   sp   

面向对象和面向过程思想

OC是面向对象的,C是面向过程的。面向对象和面向过程只是解决问题的两种不同思想

面向对象和面向过程的区别

以用电脑听歌为例子

面向过程关注的是解决问题的步骤,数据和操作分离

  • 打开电脑
  • 播放电脑中的歌曲
  • 关闭电脑

面向对象,Everything is an object!一切都是对象,数据和操作不分离,思考解决问题需要多少个对象,不用分析需要多少步骤解决问题

  • 电脑
  • 开机
  • 播放歌曲  
  • 关机

区别分析

  • 面向过程关注的是解决问题需要哪些步骤
  • 面向对象关注的是解决问题需要哪些对象
  • 没有开发经验很难感受到它们的区别,两种思想都能达到解决问题的目的,但是解决思路不一样

现实生活中面向对象的例子

  • 想打电话、发短信 》 找手机,不用分析电话要怎样才能拨通
  • 去饭店吃饭 》 找服务员,不用分析怎么到厨房炒菜
  • 汽车坏了 》 找汽车维修工,不用分析修车的步骤
  • 境界:万物皆对象

  常用术语

  • 面向过程 Procedure Oriented
  • 面向对象 Object Oriented,简称OO
  • 面向对象编程 Object Oriented Programming,简称OOP

类和对象的关系

面向对象中有2个非常重要的概念:类和对象

如何创建对象

1)       面向对象解决问题的时候必须有对象

2)       现实生活的例子:如何创造汽车对象?

  a)       需要先有汽车的建造图纸,图纸上描述清楚汽车应该具备的属性和功能(行为)

  • 属性:轮子数、时速
  • 功能(行为):跑

  b)           然后再根据图纸上的描述生成汽车

  c)           每一辆汽车都是对象,都有自己具体的属性值,都是图纸的实例

  d)           图纸是抽象的,汽车是具体的。图纸是对汽车对象的高度概括

OC中的面相对象

1)       类相当于图纸,用来描述一类事物。也就是说,要想创建对象,必须先有类

2)       利用类来创建对象,对象是类的具体存在

3)       因此,面向对象解决问题应该是先考虑需要设计哪些类,再利用类创建多少个对象 

需要设计哪些类,如何设计类

1)       类的设计,只关心3样东西:

  • 事物名称(类名):人(Person)
  • 属性:身高(height)、年龄(age)
  • 行为(功能):跑(run)、打架(fight)

2)       一般名词都是类

  • 坦克发射3颗炮弹轰掉了2架飞机(设计坦克类,飞机类,炮弹类)
  • 小明在公车上牵着一条叼着热狗的狗(人类,公车类,狗类,热狗类)

3)       拥有相同(或者类似)属性和行为的对象都可以抽像出一个类,把具有相似,或相同属性和行为的对象,高度抽象为类,具有类名、属性、行为

4)       哪个对象最清楚这个行为,就把这个行为写到哪个对象中去。打开电脑(开机)这个行为应该是属于电脑的。

定义OC的类和创建OC的对象

要描述类分2大步骤:类的声明、类的实现(定义)。跟函数类似,函数也分声明和定义。而声明一个类又需要三大要素:类名,属性,行为 

类的声明

1)   代码编写

  • 定义一个Car类,拥有2个属性:轮子数、时速,1个行为:跑
  • 类名\属性的命名规则:标示符的规则
  • 类名的命名规范:有意义、驼峰标识、首字母必须大写
 1 /*
 2  类名:Car
 3  属性:轮胎个数,时速
 4  行为:跑
 5 */
 6 //类的声明,关键字@interface后一个空格,跟一个类名,然后最后必须写@end,告诉编译器类声明完毕
 7 //类的声明用来声明对象的属性(成员变量,也叫实例变量)和行为(方法)
 8 //: NSObject 继承一个类(在Foundation框架里),让car类具备创建对象的能力
 9 //自然要加上头文件
10 #import <Foundation/Foundation.h>
11 
12 @interface Car : NSObject
13 {//花括号里用来写对象属性,不能写方法
14     //@pulic  可以让成员变量被外部指针间接的访问,
15     @public
16     int wheels;//轮胎个数
17     int speed;//时速
18 }
19 
20 //方法(行为)
21 //三要素:方法名,参数,返回值(类似函数,分声明和实现),方法的声明在类的声明里,且不能写在花括号里。
22 //方法虽然类似c的函数,但是和函数千差万别
23 //只要方法是对象的方法,则声明前必须加一个减号-,这是规则!
24 //oc方法里的任何数据类型都必须用小括号()括起来
25 //oc方法的小括号就一个作用,就是括住数据类型的。故- (void) run();是不对的!
26 - (void) run;//ok
27 @end
28 
29 //类的实现,类似于类的声明语法,也要写@end
30 @implementation Car
31 //oc方法的实现,必须写在类的实现里(类的实现就是为了写方法的实现),说清楚方法里有什么
32 - (void) run
33 {
34     NSLog(@"车子跑起来!");
35 }
36 @end
37 
38 int main()
39 {
40     //利用类创建对象
41     //在oc,想执行一些行为,必须写上一个中括号[]
42     //[行为执行者 行为名称]
43     //执行Car这个类的new行为来创建对象,分配了内存,每个对象都有自己的存储空间来存储自己的成员变量等元素
44     //对象里的成员变量,默认初始化为0,wheels是0,speed是0
45     //[Car new];//创建了一个Car类的对象,返回对象的地址(返回对象)。之后内存里存在这个对象了。
46     //oc里想操作对象,只能必须用指针去间接操作!
47     Car *p = [Car new];//把地址保存到指针里,p指向的是Car类型的对象(指针占8个字节)
48     
49     //又创建一个新对象,[Car new];每次都创建新对象
50     Car *p1 = [Car new];//默认成员变量值还是0
51     //给p指向的对象的属性赋值
52     p->wheels = 4;
53     p->speed = 200;
54     
55     NSLog(@"车子有%d个轮子,时速是:%d km/h", p->wheels, p->speed);
56     
57     //[方法执行者 方法名称],想执行一个行为,用中括号
58     //给p指向的对象发送一条run消息
59     [p run];
60     
61     //程序退出,内存被回收
62     return 0;
63 }

bubuko.com,布布扣

 

@public可以让Car对象的wheels和speed属性被外界访问

 

加上:NSObject的目的是让Car类具备创建对象的能力,也需要Foundation头文件

 

main函数的代码分析、内存分析(对象在内存中有成员)

[Car new]每次都会创建出新的对象,并且返回对象的地址,那么就应该用一个指针变量保存对象的地址

Car *c = [Car new];//用一个指针变量c指向内存中的Car对象     

设置车子对象的属性,跟用指向结构体的指针访问结构体属性一样,用->

c->wheels = 3;

c->speed = 300;

创建多个Car对象

分别只设置wheels、speed属性

Car *c1 = [Car new];

c1->wheels = 4;

Car *c2 = [Car new];

c2->speed = 250;

[c1 run];//对c1对象发消息,和c2无关

 

1个赋值给另一个,然后修改属性

Car *c1 = [Car new];

c1->wheels = 4;

c1->speed = 250;

Car *c2 = c1;

c2->wheels = 3;

[c1 run];//指针c2也指向了指针c1指向的对象,故唯一的这个对象的wheels改变为3,speed不变。

 1 /*
 2  3  类名:Person
 4  属性:whight,age(oc里叫实例变量,或成员变量)
 5  行为:走路(oc里叫方法)
 6  */
 7 #import <Foundation/Foundation.h>
 8 
 9 //1、类的声明
10 //写成员变量,和类的方法声明
11 @interface Person : NSObject
12 {
13     //实例变量
14     @public
15     int age;
16     double weight;
17 }
18 //方法声明,对象的方法必须-开头,数据类型必须()括起来
19 - (void)walk;
20 
21 @end
22 
23 //2、类的实现
24 //写方法的实现
25 @implementation Person
26 - (void) walk
27 {
28     NSLog(@"%d岁, %.2f斤 的人开始走路", age, weight);//自动换行
29 }
30 @end
31 
32 int main()
33 {
34     Person *person = [Person new];
35     person->age = 20;
36     person->weight = 100.0;
37     [person walk];//给指针person指向的人对象发送walk消息,告诉该对象调用属于这个对象的walk方法,这是oc的消息机制
38     
39     Person *person1 = [Person new];//又创建一个新的对象,用指针person1指向它,它和之前的对象完全没有关联,是开辟的新的内存空间
40     person1->age = 24;
41     person1->weight = 150;
42     [person1 walk];
43     
44     person1 = person;//指针person1指向了第一个对象(person指针指向的对象)
45     
46     return 0;
47 }

bubuko.com,布布扣

对象在内存里的变化和状态图

 

典型失误:oc类属性,默认是protected,外部无法访问,需要手动设置为public。还有一个典型的错误,oc千万不能想当然的和c++,java混淆,不用在类实现里再添加花括号了,直接写方法的实现即可。

bubuko.com,布布扣

 

和c++的不同,oc的类占据一份内存空间!在第一次使用类的时候,类被加载到内存里,即在创建对象之前,先给类分配内存空间。

bubuko.com,布布扣

 

注意:

1存放类的内存只被加载一次(第一次使用对象的时候加载对象属于的类)即可,且里面只存放方法的列表。

2内存里每个对象的存储空间内部默认都有一个指针叫isa指针,每个对象都有。

作用是:指向这个对象所对应的类(存放类的内存块),所以,所有的对象都共用一份方法,所以,类只被加载一次即可。成员变量每个对象都有自己的那一份内存,但是方法就共用一份内存

3调用方法的过程:

[person1 walk]; 执行:给指针person1指向的对象发送一条walk消息,去调用那个对象的walk方法,然后对象会顺着isa指针找到对应的类,去类里找方法,找到walk方法,就前往对应的代码去执行,就在walk方法里访问当前对象的成员变量age和weight(因为成员变量,每个对象都有自己的一份)

面向对象封装的好处

  • 更加接近人类的思考方式
  • 只需要关注对象,不需要关注步骤 

oc的对象与函数的关系

  • 对象成员变量作为函数参数
  • 指向对象的指针作为函数参数
  • 修改指针指向对象的成员
  • 修改指针的指向
 1 #import <Foundation/Foundation.h>//NSObject
 2 @interface Car : NSObject
 3 {
 4     //花括号里才能写成员变量
 5     @public
 6     int wheels;
 7     int speed;
 8 }
 9 - (void) run;
10 @end
11 
12 @implementation Car
13 - (void) run
14 {
15     NSLog(@"%d个轮子的车速是%d,跑起来了!", wheels, speed);
16 }
17 @end
18 //oc的函数和c的函数还是比较相似的,但是方法是方法,函数是函数,要区分开来!
19 //oc方法和函数是有本质区别的
20 void test(int w, int s)
21 {
22     w = 3;
23     s = 100;
24 }
25 
26 void test1(Car *newC)
27 {
28     newC->wheels = 3;
29 }
30 
31 void test2(Car *newC)
32 {
33     Car *c2 = [Car new];
34     c2->wheels = 5;
35     c2->speed = 300;
36     newC = c2;//这里实际上把参数newC指针指向的地址覆盖了!!!!故不会再影响外面的对象
37     newC->wheels = 6;
38 }
39 
40 int main()
41 {
42     Car *c = [Car new];
43     c->wheels = 4;
44     c->speed = 200;
45     //把刚创建的对象的成员变量值,传递给函数
46    // test(c->wheels, c->speed);
47    // [c run];//给对象传递run的消息
48     /*
49      打印结果是4个轮子的车速是200,跑起来了!
50      因为test函数参数是简单的值传递,故不会改变原来的值。
51      */
52     
53     //test1(c);
54    // [c run];
55     /*
56      此时打印:3个轮子的车速是200,跑起来了!
57      */
58     
59     test2(c);
60     [c run];
61     /*
62      打印4个轮子的车速是200,跑起来了!
63      */
64     
65     return 0;
66 }

test2(c);

[c run];//打印4个轮子的车速是200,跑起来了!

这段代码在内存里是这样的:指针c指向的是函数外部的对象,开始执行方式test2,给形参newC分配内存空间,newC也指向了c指向的函数外部的对象,转到对应函数代码去执行,函数内部(局部变量)创建新的对象,用新指针c2指向,然后修改对象对应的成员变量值,关键还有一步,newC指针最后指向了函数内部创建的对象,newC = c2; newC不再指向函数外部那个对象了,故不论newC指向的对象对成员变量做如何改变,对外部对象没有影响。并且,函数执行完毕,作为局部变量,存储newC的内存消失,存储c2的内存消失。但是注意:oc的对象不会自动去回收,一旦创建,一直存在内存里,除非手动释放,或者程序执行完毕。所以,函数创建的对象不会消失。但是没有指向它的指针存在了。

 

objective-c学习笔记(2)

标签:style   blog   http   color   io   ar   使用   java   sp   

原文地址:http://www.cnblogs.com/kubixuesheng/p/4035423.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!