黑马程序员--06OC类和对象

来源:互联网 发布:谷歌浏览器禁止js 编辑:程序博客网 时间:2024/05/22 14:31
                              ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1.

1.类的设计

       1.   设计类只需要关注三部分:

       类的名称 - 人(Person

       具有属性 - 比如姓名(name年龄(age)

       具有功能 - 比如吃饭(eat), 运动(sport)


       2.  类名的规范   

a.  类名的第一个字母必须大写

        b.  不能有下划线

        c.  多个英文单词用驼峰标识

2类的创建和使用

如何用OC创建类 完整的写一个函数需要函数的声明和实现.

                                完整的写一个类需要类的声明和实现.


3.类的声明

  1 格式:

类的声明以@interface开头@end结尾

类的声明必须要说明父类import父类的声明文件

类的声明中要说明属性和声明行为(成员变量和方法声明)

   2 属性:

属性声明在大括号中.

属性也叫做成员变量或者实例变量(每个实例都有自己的属性值).

对象创建时所有的成员变量默认初始化为0只能声明成员变量不能在大括号里给它们赋初值只写类型和变量名也不能用static等等修饰.

@public可以让外部的指针直接访问对象的成员变量. @public后面的属性都是public属性

    3 方法:

方法声明写在大括号外面.

方法由三部分构成:方法名,参数,返回值

OC中方法要遵循下面的要求:

a>    如果是对象调用的方法用减号标记如果是类调用的方法用加号标记.

b> 数据类型用()括起来

c> 接收的参数不能用()因为在OC中小括号就是用来括数据类型的参数要用冒号标记. 有几个参数就写几个冒号没有参数就不写.

方法不能使用static修饰. static是修饰C语言的函数的方法和函数不同.


4.类的实现 :用来实现@interface中声明的方法


类的实现要以@implementation开头@end结尾  类的实现中不需要写父类。

方法的实现先把方法声明抄过来再加个大括号在里面写实现代码。 方法内部如果要访问当前对象的成员变量直接写变量名字就可以

5.类的使用


OC中执行一个行为要使用中括号的格式[行为执行者 行为名称]即告诉OC让那个执行者去执行那个行为.

OC中操作对象只能通过指针来操作不能直接操作对象

类的声明必须放在main之前跟函数一样因为编译是从上往下的

#import <Foundation/Foundation.h>//类的声明。NSObect中包含new方法,没有这个继承Car就无法创建对象//OC中想要修改某个变量的只能用指针@interface Car : NSObject{@public // 可以让外部指针访问类的成员变量    int wheels; // Car这个类的成员变量    int speed;}//OC对象方法必须以-开头//OC方法中任何数据类型用括号扩住()//在OC中,括号中只能用来扩住数据类型,不能乱用的- (void)test;@end//类的实现@implementation Car- (void) test{    NSLog(@"车子跑起来了");}@endint main(){    //[Car new]会创建一个新的对象,并且返回该对象的地址    Car *p = [Car new];        p->speed = 250;        p->wheels = 4;        [p test];        NSLog(@"车子有轮子%d个,车子速度%d",p->speed,p->wheels);        return 0;}



1[Car new]; 这句执行Car这个类的new行为在内存中开辟一块存储空间给Car对象这个对象中有两块int空间存储它的属性wheelsspeed,并被初始化为0.

main结束时这块内存被销毁空间被回收

2

Car *p; 定义一个指针变量来指向[Car new]创建的新对象(new返回对象地址)

3

p->wheels=4; 使用这个指针来访问对象的属性 (OC对象的本质其实就是结构体). 如果属性声明中没有@public就不可以通过指针这样访问.

4

[p run]; 调用p指向的对象的run方法 (也叫做发送消息)



@interface Person : NSObject{    @public    int age;    int weight;}- (void) run;@end@implementation Person- (void) run{    NSLog(@"%d岁,%d重的人跑了一步",age,weight); // 对像方法中的变量直接调用对象中的变量}@endint main(){    Person *p = [Person new];    p->age = 20;    p->weight = 100;        Person *p1 = [Person new];    p1->age = 24;    p1->weight = 120;    [p1 run];        Person *p3 = [Person new];    p3 = p;    p3->age = 50; // 改变了最上边生产的对象的成员变量        [p run];    return 0;}



6.类在内存中的存储


类在内存中也占据存储空间一个类只占一份存储空间每个对象都占一份存储空间.

类的存储空间里只存放方法列表使用类创建对象之前会先给类分配一块存储空间把类加载进内存且只加载一次. 每个对象内部都有一个isa指针指向类所在的内存空间.

每当新建一个对象时都会在内存中分配一块存储空间给对象这块空间内部储存对象的成员变量还有一个isa指针指向类的空间(里面可以访问到类的方法).

使用指针访问对象的成员变量时访问当前对象的成员变量使用指针调用方法时访问的成员变量也是当前对象的成员变量类中只存储方法列表。对像中包含成员变量和isa



例子     [p  run]; p所指向的对象发送run消息,来到此对象后,要调用run方法,顺着isa指针找到他自己的类,在类中找到run方法后调用代码。


2.对象

1.对象与函数

位置:函数可以在文件的任意地方定义(除了类的声明里),函数是属于整个project所有的所以其实可以写在任何地方函数甚至可以写在@implementation里面和写在外面的效果是一样的.  

         方法必须声明和实现在类的定义里

  

定义:函数的定义方式是C语言的方式没有加减号参数在小括号里类型不用括号  void suma,b;. 方法的定义需要加减号小括号里是类型参数用冒号标记   - (int) sum: (int) a  :(int) b; 


调用:调用时函数使用函数名(参数)方式 sum (3,2), 方法使用[对象名 方法名]方式调用 [p  sum:3:2];.


对象方法只能由对象调用,其归对象所有   

函数的调用不依赖于对象,但函数内部不能直接通过成员变量名访问某个对象的成员变量

方法可以作为函数的参数

#import <Foundation/Foundation.h>@interface Person : NSObject{    @public    int age;    int weight;}- (void) run;@end@implementation Person- (void) run{    NSLog(@"%d岁,%d重的人跑了一步",age,weight); // 对像方法中的变量直接调用对象中的变量}@endvoid test(Person *S1){     Person *s= [Person new];     s->age = 1;     s = S1; // 只是将S1中包含的地址给了s,将s原来的地址给覆盖了,不会影响p}int main(){    Person *p = [Person new];    p->age = 20;    p->weight = 100;        test(p);        [p run];    return 0;}
对象方法只能由对象来调用,所以

- (void)test 这种写法肯定是不对的,只能是[p test]

还有函数出了@interface与@end中间不能写,其他地方都能写,方法有严格的限制。


2关于方法名 

- (int) square:(int)num; 这个方法的方法名是 square: 冒号是方法名的一部分. 比如 - (int) square; 这个方法的方法名是square. 这两个方法的名称是不一样的. 

- (int) sumOfNum1:(int)num1 andNum2:(int)num2;  这个方法的方法名是 sumOfNum1:    andNum2:  

加减号不是方法名的一部分, 而是方法类型. 

 

关于有多个参数方法的写法 

- (int) sumOfNum1:(int)num1 andNum2:(int) num2;

1) 每个形参名称后面要有空格, 和后面的方法名部分分隔

2) 可以不写and部分, 比如- (int) sum:(int)num1 :(int)num2; 但是可读性不好. 苹果推荐把方法名写的可读性很好就是看到方法名就知道输入什么样的参数. 有的方法名长得像句子一样, 但是可读性很好

类方法:


类方法 - 使用类名来调用的方法. + 标记.

使用场合使用类方法代替对象方法可以提高性能.


类方法比对象方法优化体现在不用创建对象就能执行行为.在内存中, +识别为类方法,直接去类的存储空间中调用方法对象方法则需要通过对象指针访问对象,通过isa指针访问类空间,才能调用到方法.对象方法中可以包含类方法

 

+开头的方法和 -开头的方法是不同的.类不能调用对象的方法对象不能调用类的方法.否则(编译链接可以通过)运行时会报错 -找不到相应的类/对象方法.

 

因为类方法和对象方法不同所以可以有同名的类方法和对象方法.

+ (void) test;

- (void) test;

上面两个方法是可以同时存在的.但是不能有两个同名的对象方法或两个同名的类方法.

 

注意成员变量也叫实例变量,是只有实例(对象)才有的变量,类没有成员变量在内存中,对象里有存储空间存放成员变量的值,类的空间里是没有存放成员变量的地方的,所以类没有成员变量的值,类方法不能访问成员变量.

 

所以, 如果方法中需要访问成员变量,就要写成对象方法如果不需要访问成员变量,就可以写成类方法.

 

类方法注意

a.不依赖于对象,执行效率高

b.能用类方法(不需要成员变量)尽量用类方法.

c. 当方法内部不需要访问成员变量时,就可以使用类方法.


#import <Foundation/Foundation.h>@interface Person : NSObject{    @public    int _age;}- (void)test; // 对象方法+ (void)test; // 类方法@end@implementation Person- (void)test{    NSLog(@"123");}+ (void)test{    //NSLog(@"%d",_age);这种写法不对,是因为age是一个实例变量,那么也就是说,它只能用对象方法来调用,类中是没有对应的成员变量的        NSLog(@"345");}@endint main(){    Person *p = [Person new];    p->_age = 20;        [p test];        [Person test];        return 0;}

何时使用类方法:
当方法中不包含形参的时候
#import <Foundation/Foundation.h>@interface Jisuanqi : NSObject+ (int)sumofNum1:(int)Num1 andNum2:(int)Num2;+ (int)averofNum1:(int)Num1 andNum2:(int)Num2;@end@implementation Jisuanqi+ (int)sumofNum1:(int)Num1 andNum2:(int)Num2{    return Num1 + Num2;}+ (int)averofNum1:(int)Num1 andNum2:(int)Num2{    int a = [Jisuanqi sumofNum1:(int)Num1 andNum2:(int)Num2];        return a/2;}@endint main(){    int i = [Jisuanqi sumofNum1:10 andNum2:12];        int j = [Jisuanqi averofNum1:12 andNum2:20];       NSLog(@"sum=%d,aver=%d",i,j);}


0 0