OC--面向对象初识

来源:互联网 发布:js判断加载css样式 编辑:程序博客网 时间:2024/05/21 00:49

一、面向对象概述



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


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

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。 

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
面向过程关注的是解决问题需要哪些步骤;面向对象关注的是解决问题需要哪些对象

例如五子棋,面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就解决了。

而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为 1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的i变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。

可以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。

用面向对象思考问题更符合我们人的思考方式。 
其实我们人现实生活中都是在面向对象。比如:去饭店吃饭,你只要找服务员,说明吃什么就可以了,有必要还了解这个菜是怎么做的,是哪里来的,怎么去种这个菜吗? 
面向对象也可以说是从宏观方面思考问题,而面向过程可以说是从细节处思考问题。在面向对象中,也存在面向过程。

2.常用术语
>面向过程 Procedure Oriented
>面向对象 Object Oriented,简称OO
>面向对象编程 Object Oriented Programming,简称OOP


二、类和对象的关系

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

1)OC中的类相当于图纸,用来描述一类事物。也就是说,要想创建对象,必须先有类
2)OC利用类来创建对象,对象是类的具体存在
3)因此,面向对象解决问题应该是先考虑需要设计哪些类,再利用类创建多少个对象

1、类的声明和实现

1)类的设计,只关心3样东西:
>事物名称(类名):人(Person)
>属性:身高(height)、年龄(age)
>行为(功能):跑(run)、打架(fight)

2)类的设计:
1> 类名
* 类名的第一个字母必须是大写
* 不能有下划线
* 多个英文单词,用驼峰标识
2> 属性
3> 行为(功能)


3)代码实现
完整地写一个函数:需要函数的声明和定义(实现)
完整地写一个类:类的声明和实现

1.类的声明
声明对象的属性、行为

>成员变量
@interface的大括号{}中声明的变量:wheels、speed
@interface的大括号和函数的大括号是不一样的
默认会初始化为0

@interface Car : NSObject     // : NSObject 目的是:让Car这个类具备创建对象的能力
{     // 用来声明对象属性(实例变量\成员变量,默认会初始化为0)
    // @public可以让外部的指针间接访问对象内部的成     员变量
    @public
    int wheels; // 轮胎个数
    int speed; // 时速(xxkm/h)
}

// 方法(行为):方法名、参数、返回值(声明、实现)
// 只要是OC对象的方法,必须以减号 - 开头
// OC方法中任何数据类型都必须用小括号()扩住
// OC方法中的小括号():括住数据类型
- (void)run;


@end


2.类的实现
用来实现@inteface中声明的方法
@implementation Car
// 方法的实现(说清楚方法里面有什么代码)


- (void)run
{
    NSLog(@"车子跑起来了");
}


@end


3.创建对象


在OC中,想执行一些行为,就写上一个中括号[行为执行者 行为名称],利用类来创建对象
     
执行Car这个类的new行为来创建新对象, 定义一个指针变量p,p将来指向的是Car类型的对象
[Car new]每次都会创建出一个新对象,并且会返回新对象本身(新对象的地址),那么就应该用一个指针变量保存对象的地址
   


    用一个指针变量c指向内存中的Car对象      


Car *p = [Car new];
    // 给p所指向对象的wheels属性赋值
    p->wheels = 4;
    p->speed = 250;
   
    // 给p所指向对象发送一条run消息
    [p run];
   
    NSLog(@"车子有%d个轮子,时速位:%dkm/h", p->wheels, p->speed);

注意:
>成员变量不能在{}中进行初始化、不能被直接拿出去访问
>方法不能当做函数一样调用
>成员变量\方法不能用static等关键字修饰,别跟C语言混在一起
>类的实现可用写在main函数的后面,主要声明在前面就行了

错误:
>只有类的声明,没有类的实现
>漏了@end
>@interface和@implementation嵌套
>两个类的声明嵌套
>成员变量没有写在括号里面
>方法的声明写在了大括号里面
细节:
>方法只有声明,没有实现(经典错误)
>方法没有声明,只有实现(编译器警告,但是能调用,OC的弱语法)
>编译的时候:访问没有的成员变量直接报错,访问没有的方法,只是警告


4.完整代码显示

/*人类名:Person属性(成员变量\实例变量):体重、年龄行为(方法):走路、吃*/#import <Foundation/Foundation.h>/*1.类的声明    * 成员变量    * 方法的声明*/@interface Person : NSObject{    @public    int age;    double weight;}- (void)walk;- (void)eat;@end


// 2.类的实现
@implementation Person// 实现@interface中声明的方法- (void)walk{    NSLog(@"%d岁、%f公斤的人走了一段路", age, weight);}- (void)eat{    NSLog(@"%d岁、%f公斤的人在吃东西", age, weight);}@end



int main(){    // 在使用类创建对象之前,会将类加载进内存    Person *p = [Person new];    p->age = 20;    p->weight = 40;       [p eat];    [p walk];       Person *p2 = [Person new];    p2->age = 30;    p2->weight = 60;    [p2 eat];    [p2 walk];          return 0;}


内存分析


三、OC对象跟函数
1)方法
1.对象方法都是以减号 -
2.对象方法的声明必须写在@interface和@end之间
   对象方法的实现必须写在@implementation和@end之间
3.对象方法只能由对象来调用
4.对象方法归类\对象所有


2)函数
1.函数能写在文件中的任意位置(@interface和@end之间除外),函数归文件所有
2.函数调用不依赖于对象
3.函数内部不能直接通过成员变量名访问某个对象的成员变量
#import <Foundation/Foundation.h>


@interface Person : NSObject
@end


@implementation Person
@end


@interface Car : NSObject
{// 成员变量\实例变量
    //int wheels = 4; 不允许在这里初始化
    //static int wheels; 不能随便将成员变量当做C语言中的变量来使用
    @public
    int wheels;
}


- (void)run;
- (void)fly;
@end


int main()
{
    // wheels = 10;
    /*
    Car *c = [Car new];
    c->wheels = 4;
    //run();
    
    [c run];
    */
    
    void test2();
    
    test2();
    
    return 0;
}


@implementation Car


- (void) fly
{
    
}


/*
void test2()
{
    NSLog(@"调用了test2函数-%d", wheels);
}*/


void test()
{
    NSLog(@"调用了test函数");
}


- (void)run
{
    test();
    NSLog(@"%d个轮子的车跑起来了", wheels);
}
@end



四、
类的合理设计

/*
学生
成员变量:性别、生日、体重、狗(体重、毛色,吃、跑)
方法:吃、跑步、遛狗(让狗跑)、喂狗(让狗吃)
*/
#import <Foundation/Foundation.h>typedef enum {  //枚举    SexMan,    SexWoman} Sex;typedef struct {   //结构体    int year;    int month;    int day;} Date;//声明---------狗----------------@interface Dog : NSObject{    @public    double weight; // 体重    }- (void)eat;- (void)run;@end//实现-----------狗--------------@implementation Dog- (void)eat{    // 每吃一次,体重就加1    weight += 1;    //weight = weight +  1;    NSLog(@"狗吃完这次后的体重是%f", weight);}- (void)run{    weight -= 1;    NSLog(@"狗跑完这次后的体重是%f", weight);}@end



//声明--------学生-----------@interface Student : NSObject{    @public    Sex sex; // 性别    Date birthday; // 生日    double weight; // 体重(kg)           // 重点:狗    Dog *dog;}- (void)eat;- (void)run;- (void)print;- (void)liuDog;- (void)weiDog;@end//实现----------学生--------------@implementation Student- (void)liuDog{    // 让狗跑起来(调用狗的run方法)    [dog run];}- (void)weiDog{    // 让狗吃东西(调用狗的eat方法)    [dog eat];}- (void)print{    NSLog(@"性别=%d, 姓名=%s, 生日=%d-%d-%d", sex,birthday.year, birthday.month, birthday.day);}- (void)eat{    // 每吃一次,体重就加1    weight += 1;    //weight = weight +  1;    NSLog(@"学生吃完这次后的体重是%f", weight);}- (void)run{    weight -= 1;    NSLog(@"学生跑完这次后的体重是%f", weight);}@end



int main(){    Student *s = [Student new];        Dog *d = [Dog new];    d->curColor = ColorGreen;    d->weight = 20;    s->dog = d;            [s liuDog];        [s weiDog];    return 0;}void test(){    Student *s = [Student new];    s->weight = 50;        // 性别    s->sex = SexMan;        // 生日    Date d = {2011, 9, 10};    s->birthday = d;        s->name = "Jack";        /*     s->birthday.year = 2011;     s->birthday.month = 9;     s->birthday.day = 10;     */           [s print];}


五、带参数的方法

1.方法声明

单个参数:

- (方法返回值类型) 方法名:(参数类型) 参数名;

OC方法中,一个参数对应一个冒号,冒号也是方法名的一部分
- (int)pingFang:(int)num;


多个参数:

- (方法返回值类型) 方法名:(参数类型)参数名1 方法名:(参数类型)参数名2;


方法名严格按照参数名的定义形式,看上去简单明了。 

//方法名:sumWithNum1:andNum2:

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

- (int)sumWithNum1:(int)num1 andNum2:(int)num2 andNum3:(int)num3;


2.方法实现


- (int)pingFang:(int)num
{
    return num * num;
}



- (int)sumWithNum1:(int)num1 andNum2:(int)num2
{
    return num1 + num2;
}


3.方法调用


JiSuanQi *jsq = [JiSuanQi new]; 

int a = [jsq sumWithNum1:20 andNum2:5];


六、匿名对象

用指针创建对象:

Car *c = [Car new];


c->speed = 250; 


[c run];


匿名对象:


[Car new]->speed = 300;
    
[[Car new] run];

直接用对象指向成员变量,调用方法,每次执行[Car new]都会创建一个新对象,每个操作都在新创建的对象中,浪费系统系能。不要写这样的代码!


0 0
原创粉丝点击