④--OC面向对象

来源:互联网 发布:北京seo公司 编辑:程序博客网 时间:2024/06/05 05:45

    面向对象的引入——在我们熟悉的现实世界中,一切事物都是对象。对象可以是有形的,比如房屋、汽车、飞机、动物、植物;也可以是无形的,比如一项计划。对象可以是一个简单的个体,比如一个人;也可以由诸多其他对象组合而成,比如一个公司有多个部门,每个部门又由许多人组成。对类似的对象进行抽象,找出其共同属性,便构成一种类型。这些都是我们在现实世界中所熟悉的概念和方法。

编写程序的目的是描述和解决现实世界中的问题,第一步就是要将现实世界中的对象和类如实地反映在程序中。作为一种面向对象的程序设计语言,OC支持这种抽象。将抽象后的数据和函数封装在一起,便构成了 OC的“类”。

1.采用面向对象的编程方法时,要注意区分类和对象的概念:

    在面向过程的结构化程序设计中,程序的模块是由函数构成的,函数将逻辑上相关的语句与数据封装,用于完成特定的功能。在面向对象程序设计中,程序模块是由类构成的。类是对逻辑上相关的函数与数据的封装,它是对问题的抽象描述。因此,后者的集成程度更高,也就更适合用于大型复杂程序的开发。 

不妨从另一个更简单的角度来理解类。首先回顾一下基本数据类型,比如 int,double,bool 等。当声明一个基本类型的变量时,究竟声明了什么呢,看下面的语句: 

int i; BOOL b;

 显然这声明了变量 i 是用于存储 int 型数据的,变量 b 是用来存放 bool 型数据的。但是变量声明的意义不只是这个,另一个同样重要的意义常被我们忽略了,这就是限定对变量的操作。例如对 i 可以进行算术运算、比较运算等,对 b 45可以进行逻辑运算、比较运算。这说明每一种数据类型都包括了数据本身的属性以及对数据的操作。 无论哪一种程序语言,其基本数据类型都是有限的,简单地C的基本数据类型也远不能满足描述现实世界中各种对象的需要。于是 OC的语法提供了对自定义类型的支持,这就是类。

类实际上相当于一种用户自定义的类型,原则上我们可以自定义无限多种新类型。因此不仅可以用 int 类型的变量表示整数,也可以用自定义类的变量表示“时钟”、 “汽车”、“几何图形”或者“人”等对象。正如基本数据类型隐含包括了数据和操作,在定义一个类时也要说明数据和操作。 当定义了一个类之后,便可以定义该类的变量,这个变量就称为类的对象或实例,这个定义的过程也称为类的实例化。

总的来说,类相当于是模板,而对象是成品。

2.如何设计一个类,并根据类来创建对象呢?(如何用OC语言以代码的形式表现出来)

一般来说,类的设计包括这几个部分

1>类名

*类名的第一个字母必须是大写

*不能有下划线

*多个英文单词,用驼峰标识

2>属性

3>行为(功能)


代码包括两大部分类的声明和类的定义(实现

类的定义使用的关键字是@iterface和@end组合;类的实现使用的是@implementation和@end关键字组合

下面是根据一个定义一个Car类

声明:

@interface Car : NSObject{ // 声明对象属性    int wheels; // 轮胎个数    int speed; // 时速(xxxkm/h)}@end

实现:

// 2.类的实现@implementation Car@end

这样就创建了一个有两个属性、没有方法的汽车类Car,

在OC语言中可使用new来实例化一个类的对象(new 实际上是从OC的根类NSObject类中继承而来的方法):

int main(){    // 在OC中,想执行一些行为,就写上一个中括号[行为执行者 行为名称]    // 利用类来创建对象    // 执行了Car这个类的new行为来创建对象    [Car new];        return 0;}

实际上new方法会返回一个指向创建的对象的指针,我们可以用一个Car类型的指针来接受返回的对象,并且修改这个被实例化的对象的wheels属性值,代码如下:

int main(){    // 在OC中,想执行一些行为,就写上一个中括号[行为执行者 行为名称]    // 利用类来创建对象    // 执行了Car这个类的new行为来创建对象        // 在OC中创建对象返回的是该类型的指针    // [Car new]会创建一个新对象,并且会返回新对象本身(新对象)    Car *p = [Car new];    p->wheels = 4;        return 0;}
此时会发现,编译器报错,原因是属性的默认访问权限是私有的,要想修改属性的值,必须使用@public关键字类声明,于是修改类的声明部分:


@interface Car : NSObject{ // 声明对象属性    @public    int wheels; // 轮胎个数    int speed; // 时速(xxxkm/h)}@end
这样main函数中的代码就能顺利执行了。


3.为类添加行为和注意点

  添加行为首先要在类的声明部分添加方法声明,

#import <Foundation/Foundation.h>@interface Car : NSObject{ // 声明对象属性    @public    int wheels; // 轮胎个数    int speed; // 时速(xxxkm/h)}// 方法(行为):方法名、参数、返回值(声明、实现)// 对象的方法必须以减号-开头// OC方法中任何数据类型都必须用小括号()括住// OC方法中的小括号():括住数据类型-(void) run;@end

上面的代码是在类的声明中添加了一个跑得方法,方法名为run,添加了方法以后还要再类的实现部分添加方法的实现代码:

@implementation Car// 方法的实现(说清楚方法里面有什么代码)-(void)run{    NSLog(@"车子跑起来了");}@end

要让类的对象调用该方法,可以在main函数中添加如下的代码:

[p run];

4.方法与成员变量的调用注意点

每个被实例化的对象都占据自己独立的内存,包括它的成员变量的内容,当一个类的实例(也就是对象),调用方法中有对属性值的引用,则是使用他自己的属性值,而与其他类的属性无关。看下面的代码:

/* 人 类名:Person 属性(成员变量、实例变量):体重、年龄 行为(方法):走路、 *//* 1.类的声明    *成员变量    *方法的声明 */#import <Foundation/Foundation.h>@interface Person : NSObject{    // 成员变量    @public    int age;    double weight;}//方法声明-(void)walk;//没有参数就不用小括号-(void)eat;@end//2类的实现@implementation Person-(void)walk{    NSLog(@"%d岁的人走了一段路", age);}-(void)eat{    NSLog(@"体重%f的人吃东西", weight);}@endint main(){    Person *p = [Person new];    p->age = 20;    p->weight = 50.0;    [p walk];        Person *p2 = [Person new];    p2->weight = 60.0;    [p2 eat];    return 0;}


执行的结果是:


2014-12-18 15:11:21.449 a.out[4870:507] 20岁的人走了一段路2014-12-18 15:11:21.451 a.out[4870:507] 体重60.000000的人吃东西

5.OC对象跟函数参数

OC对象被当做函数的参数经常会一起一些意想不到的问题,但只要认清一点就可以很好地把我,避免出错:

OC对象是指向内存中实例化的对象的指针。看下面的例子:

// 类的声明和实现部分@interface Car : NSObject{    @public    int wheels;    int speed;}-(void)run;@end@implementation Car-(void)run{    NSLog(@"%d个轮子,速度为%dkm/h的车子跑起来", wheels, speed);}@end

void test1(Car *newC){    newC->wheels = 5;//同一指向的指针修改值,最终改变了c}


int main(){    Car *c = [Car new];    c->wheels = 4;    c->speed = 250;    test1(c);    [c run];    return 0;}

首先内存中实例化了一个Car类型 并由变量c指向了它,语句test1(c)执行之后,形参newC有了与c相同的值,

函数的内部语句newC->wheels = 5;执行后将newC指向的那个对象的wheels改为了5,这同时也是c指向的对象,于是在执行[c run];语句时,自然会输出:

5个轮子,速度为250km/h的车子跑起来

在看下面的例子:

void test2(Car *newC)//指针赋值是将指向的地址赋值*********其实就是改变指向{    Car *c2 = [Car new];    c2->wheels = 5;    c2->speed = 300;        newC = c2; //改变了newC的指向    newC->wheels = 6;//不同指向的指针修改值,最终没有改变c}

int main(){    Car *c = [Car new];    c->wheels = 4;    c->speed = 250;        //test(c->wheels, c->speed);    //test1(c);    test2(c);    [c run];    return 0;}

在这个例子中,自始至终没有和c相同指向的指针去修改它所指向的实例对象,所以输出结果为:

4个轮子,速度为250km/h的车子跑起来

6.OC方法跟函数的区别

方法

 1.对象方法都是以减号-开始

 2.对象方法的声明必须写在@interface@end之间

    对象方法的实现必须写在@implementation@end之间

 3.对象方法只能由对象来调用,

 4.对象方法归类、对象所有 

 

 函数

 1.函数能写在文件中的任意位置(@interface@end之间除外),函数归文件所有

 2.函数调用不依赖于对象

 3.函数内部不能调用对象的成员变量


7.方法声明和实现(类方法和对象方法,带参数的方法)

当OC方法中带参数时,OC方法中一个参数对应一个冒号,函数名通常中通常语义中包含第一个参数名的描述,如

-(int)sumWithNum1:(int)num1;  // 带一个参数的方法

当有多个参数是从第二个参数起,以空格开始依次添加参数描述信息、冒号、参数类型、参数名,如

-(int)sumWithNum1:(int)num1 andNum2:(int)num2; // 官方建议这样写

每个方法中有几个参数,方法名中就有几个冒号,如


-(int)pingFang:(int)num;

方法名为:pingFang:

也就意味着所有的描述信息加冒号组成了方法名-(int)sumWithNum1:(int)num1 andNum2:(int)num2; 

方法名为:sumWithNum1: andNum2:

8.匿名对象

有时候利用OC创建一个对象后并没有用该对象类型的指针指向它,而是直接调用了方法或者做了其他事情,这样的对象就叫做匿名对象(没有指向它的变量名)。如

#import <Foundation/Foundation.h>@interface Car : NSObject{    @public    int speed;}-(void)run;@end@implementation Car-(void)run{    NSLog(@"速度为%d的车跑起来", speed);}@endint main(){//    Car *c = [Car new];//    //    c->speed = 250;//    [c run];        [Car new]->speed = 300;    [[Car new] run];//造成内存泄露    return 0;}


上面的代码中创建了两个不同的匿名对象,因而当第二个匿名对象执行run方法的时候,其值与第一个对象无关,程序执行的结果为:

速度为0的车跑起来


0 0
原创粉丝点击