标签:style blog http color io ar 使用 java sp
OC是面向对象的,C是面向过程的。面向对象和面向过程只是解决问题的两种不同思想
以用电脑听歌为例子
面向过程关注的是解决问题的步骤,数据和操作分离
面向对象,Everything is an object!一切都是对象,数据和操作不分离,思考解决问题需要多少个对象,不用分析需要多少步骤解决问题
区别分析
常用术语
面向对象中有2个非常重要的概念:类和对象
1) 面向对象解决问题的时候必须有对象
2) 现实生活的例子:如何创造汽车对象?
a) 需要先有汽车的建造图纸,图纸上描述清楚汽车应该具备的属性和功能(行为)
b) 然后再根据图纸上的描述生成汽车
c) 每一辆汽车都是对象,都有自己具体的属性值,都是图纸的实例
d) 图纸是抽象的,汽车是具体的。图纸是对汽车对象的高度概括
1) 类相当于图纸,用来描述一类事物。也就是说,要想创建对象,必须先有类
2) 利用类来创建对象,对象是类的具体存在
3) 因此,面向对象解决问题应该是先考虑需要设计哪些类,再利用类创建多少个对象
1) 类的设计,只关心3样东西:
2) 一般名词都是类
3) 拥有相同(或者类似)属性和行为的对象都可以抽像出一个类,把具有相似,或相同属性和行为的对象,高度抽象为类,具有类名、属性、行为
4) 哪个对象最清楚这个行为,就把这个行为写到哪个对象中去。打开电脑(开机)这个行为应该是属于电脑的。
要描述类分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 }
@public可以让Car对象的wheels和speed属性被外界访问
加上:NSObject的目的是让Car类具备创建对象的能力,也需要Foundation头文件
main函数的代码分析、内存分析(对象在内存中有成员)
[Car new]每次都会创建出新的对象,并且返回对象的地址,那么就应该用一个指针变量保存对象的地址
Car *c = [Car new];//用一个指针变量c指向内存中的Car对象
设置车子对象的属性,跟用指向结构体的指针访问结构体属性一样,用->
c->wheels = 3;
c->speed = 300;
分别只设置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 }
对象在内存里的变化和状态图
典型失误:oc类属性,默认是protected,外部无法访问,需要手动设置为public。还有一个典型的错误,oc千万不能想当然的和c++,java混淆,不用在类实现里再添加花括号了,直接写方法的实现即可。
和c++的不同,oc的类占据一份内存空间!在第一次使用类的时候,类被加载到内存里,即在创建对象之前,先给类分配内存空间。
注意:
1存放类的内存只被加载一次(第一次使用对象的时候加载对象属于的类)即可,且里面只存放方法的列表。
2内存里每个对象的存储空间内部默认都有一个指针叫isa指针,每个对象都有。
作用是:指向这个对象所对应的类(存放类的内存块),所以,所有的对象都共用一份方法,所以,类只被加载一次即可。成员变量每个对象都有自己的那一份内存,但是方法就共用一份内存
3调用方法的过程:
[person1 walk]; 执行:给指针person1指向的对象发送一条walk消息,去调用那个对象的walk方法,然后对象会顺着isa指针找到对应的类,去类里找方法,找到walk方法,就前往对应的代码去执行,就在walk方法里访问当前对象的成员变量age和weight(因为成员变量,每个对象都有自己的一份)
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的对象不会自动去回收,一旦创建,一直存在内存里,除非手动释放,或者程序执行完毕。所以,函数创建的对象不会消失。但是没有指向它的指针存在了。
标签:style blog http color io ar 使用 java sp
原文地址:http://www.cnblogs.com/kubixuesheng/p/4035423.html