黑马程序员_iOS开发之OC之面向对象之思想、类和对象

来源:互联网 发布:linux 网络学习 编辑:程序博客网 时间:2024/06/09 14:46

1、OC类和对象的创建

般名词都是类,类是对象的抽象,对象是类的具体实例。

类的设计

1>类名

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

* 不能有下划线

* 多个英文单词,用驼峰表识(FlyAir)

2> 属性(成员变量)

3> 行为(功能方法)

当不知道行为该交给哪个类时,选择最了解这个行为的类做这个行为,就像定义电脑这个类,就有行为是开机,初学者感觉这不是人的功能吗?实际上电脑这个类更了解电脑自身开机,人只是调用电脑类的一个对象实现开机,所以开机是电脑类的行为功能。

2、OC类和对象创建实例

/*

 类名:Car

 属性:轮胎个数、时速(速度)

 行为:跑

*/

// 因为使用了NSObject

#import <Foundation/Foundation.h>

// 完整地写一个函数:函数的声明和定义(实现)

// 完整地写一个类:类的声明和实现

// 1.类的声明

// 声明对象的属性、行为

//:NSObject目的是:让Car这个类具备创建对象的能力

@interface Car : NSObject

{

    //此处的大括号,用来声明对象属性(实例变量\成员变量,默认会初始化为0)

    // @public可以让外部的指针间接访问对象内部的成员变量

    @public

    int wheels; // 轮胎个数

    int speed; // 时速(xxkm/h

}

// OC的方法和C中的函数写法有很大的区别

// 方法(行为、功能):方法名、参数、返回值(声明、实现)

// 只要是OC对象的方法,必须以减号 - 开头

// OC方法中任何数据类型都必须用小括号()括住

// OC方法中的小括号():括住数据类型

- (void)run;

@end


// 2.类的实现

// 用来实现@interface中声明的方法

@implementation Car

//方法的实现(说清楚方法里面有什么代码)

// 属性操作很像C中的结构体,方法操作很像C中的函数,声明在@interface,实现在@implementation有实现

- (void)run

{

    NSLog(@"车子跑起来了");

}

@end

int main()

{

    // OC,想执行一些行为,就写上一个中括号[行为执行者 行为名称 ]

    // 利用类来创建对象

    // 执行了Car这个类的new行为来创建新对象

    // 行为执行者为类Car,行为名称是new,创建一个这个类的对象

    // 定义了一个指针变量pp将来指向的是Car类型的对象

    // [Car new]每次都会创建出一个新对象,并且会返回新对象本身(新对象的地址)

   

       // OC中对对象的操作是用指针

      //成员变量操作类似C语言中的结构体,方法操作类似指向函数的指针

   // 就像用结构体类型创建一个变量,只赋给指向这个结构体变量的指针变量,不用其他操作方式


    Car *p = [Car new];

    Car* p2 = [Car new];

    p2->wheels = 5;

    p2->speed = 300;

    // 实际上,类就像结构体一样,是用户自己创建的新类型,可以说成或想象成C语言中的构造类型。

    // OC类和对象的本质就是结构体

    // p所指向对象的wheels属性赋值,操作和结构体操作一样

    p->wheels = 4;

    p->speed = 250;

    

    // p所指向对象发送一条run消息 (OC消息机制)

    [p run];

    NSLog(@"车子有%d个轮子,时速为:%dkm/h", p->wheels, p->speed);

    return 0;

}




/*

 

 类名:Person

 属性(成员变量、实例变量):体重weight、年龄

 行为(方法):走路

*/

#import <Foundation/Foundation.h>

/*

 1.类的声明

    *成员变量

    *方法的声明

 2.类的实现

 */

@interface Person : NSObject

{

    //成员变量(必须在大括号里面)

    @public

    int age;

    double weight;   

}

// 方法声明;

- (void)walk;

@end


@implementation Person

//实现@interface中声明的方法

- (void)walk

{

    NSLog(@"%d岁、%f公斤走路",age ,weight);

}

@end


int main()

{

    //对象操作只能用指针操作,因为new创建出来的对象没有名字

    //在使用类创建对象之前,会先将类加载进内存,而且只加载一次,所有这个类在内存中是创建最早的

    Person* p = [Person new];

    p->age = 20;

    p->weight = 50.0;

    [p walk];//消息机制

    // 每个对象内部都有一个默认指针isa,这个指针就指向这个对象所指向的类,类在内存中也要分配内存,只存储方法声明

    Person* p2 = [Person new];

    p2->age = 30;

    p2->weight = 60.0;

    [p2 walk];//消息机制,给p2所指向的对象发送walk消息

    return 0;

}


3、类和函数使用注意点

#import <Foundation/Foundation.h>

@interface Car : NSObject

{

    //成员变量

    @public

    int wheels;

    int speed;

}

- (void)run;

@end


@implementation Car

- (void)run

{

    NSLog(@"%d个轮子,速度%dkm/h的车子跑起来", wheels, speed);

}

@end


void test(int w, int s)

{

    w = 20;

    s = 200;

}

// 只要搞清楚,所有的操作,最终都是对内存的操作,不同的内存互不影响

void test1(Car* newC)

{

    newC->wheels = 5;

}

//此函数调用完毕后,指针变量的内存会自动回收,但是所创建的对象内存,不能自动回收,可以手动回收,也可以等到main函数执行完后自动回收

void test2(Car *newC)

{

    Car *c2 = [Car new];

    c2->wheels = 5;

    c2->speed = 300;

    newC = c2;

    newC->wheels = 6;

}

int main()

{

    // 在使用这个类先加载到内存,即先为类分配内存空间,才能用这个类创建对象

    Car* c = [Car new];

    c->wheels = 4;

    c->speed = 250;

    test2(c);

    test1(c);

    test(c->wheels, c->speed);

    [c run];

    return 0;

}





4、类的合理设计

类的合理设计

/*

 学生

    成员变量:性别、生日、体重、最喜欢的颜色、狗(体重、毛色)

    成员方法:吃、跑步、遛狗(让狗跑,即调用狗跑这个方法)、喂狗(让狗吃,同上)

 */

#import <Foundation/Foundation.h>

typedef struct

{

    int year;

    int month;

    int day;

}Date;

/*

typedef enum sex

{

    man,

    woman

}mysex;

*/

// 注意:枚举类型的取值,要以枚举类型名开头,易读

typedef enum

{

    SexMan,

    SexWoman

}Sex ;


typedef enum {

    ColorBlack,

    ColorRed,

    ColorGreen

}Color;

@interface Dog : NSObject

{

    @public

    double weight;

    Color curColor; //毛色

}

- (void) eat;

- (void)run;

@end


@implementation Dog

- (void) eat

{

    weight = weight +1;

    NSLog(@"狗吃完这次后的体重是%f", weight);

}

- (void)run

{

    weight = weight - 1;

    NSLog(@"狗跑完这次后的体重是%f", weight);

}

@end


@interface Student : NSObject

{

    @public

    Sex sex;

    Date birthday;

    double weight;

    Color  favColor;

    char * name;

    // 重点:狗

    Dog * dog ;

}

- (void) eat;

- (void)run;

- (void)print;

- (void)liuDog;

- (void)weiDog;

@end


//只有类的声明,编译可以通过,链接通不过,因为没有类的实现,实际和函数的声明和实现有点像

@implementation Student

- (void) eat

{

    weight = weight +1;

    NSLog(@"学生吃完这次后的体重是%f", weight);

}

- (void)run

{

    weight = weight - 1;

    NSLog(@"学生跑完这次后的体重是%f", weight);

}

- (void)print

{

    NSLog(@"性别=%d, 喜欢的颜色=%d, 姓名=%s,生日=%d-%d-%d",sex,favColor,name,birthday.year,birthday.month,birthday.day);

}

- (void)liuDog

{

    //让狗跑起来(调用狗的run方法)

    [dog run];

}

- (void)weiDog

{

    //让狗吃东西(调用狗的eat方法)

    [dog eat];

}

@end

int main()

{

    Student* s  = [Student new];

    //s->dog = [Dog new];


    Dog * d = [Dog new];

    d->weight = 20;

    d->curColor = ColorGreen;

    //先创建一个Dog类实例,再赋值给Student类的成员变量Dog类s对象

    //只能间接赋值,因为双重对象无法直接赋值

    //如果是成员变量是结构体,则可以

    s->dog = d;

    

    [s liuDog];

    [S weiDog];

    return 0;

}

void test()

{

    // 让指针访问内部的成员变量,要加关键字@public

    s->weight = 50;

    // 性别

    s->sex = SexMan;

    //生日

    //s->birthday = {2011, 9, 10};//这种写法错误的

    // Date d = {2011, 9, 10};//在定义变量的同时才可以赋值

    //结构体的嵌套操作时,符号“->”是指针间接操作时使用,结构体内部的成员操作用符号“.”

    /*

     //可以,方法一

     s->birthday.year = 2011;

     s->birthday.month = 9;

     s->birthday.day = 10;

     */

    //可以,方法二(更简洁)

    Date d = {2011910};

    s->birthday = d;    

    [s eat];

    [s run];

    [s print];

}

5、方法的声明和实现

/*

 计算器类

 */


#import <Foundation/Foundation.h>

//类名表示规则:第一个字母大写,命名为驼峰方法

@interface JiSuanQi : NSObject

// 方法名:pi

- (double)pi;

// 方法名:pingFang   OC中不允许两个方法名一样

//- (int)pingFang;

//OC方法中,一个参数对应一个冒号,冒号放到数据类型前

//方法名:pingFang:   冒号也是方法名的一部分

- (int)pingFang:(int)num;

//- (int)sum : (int)num1 : (int)num2;可读性不好,改进如下

// 方法名:sumWithNum1:andNum2:

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

@end


@implementation JiSuanQi

- (double)pi

{

    return 3.14;

}

//OC方法中,一个参数对应一个冒号,冒号放到数据类型前

//方法命名规则:第一个字母小写,命名为驼峰方法

- (int)pingFang:(int)num

{

    return num * num;

}

/*- (int)sum : (int)num1 : (int)num2

{

    return num1 + num2;

}*/

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

{

    return num1 + num2;

}

@end


int main()

{

    JiSuanQi * jsq = [JiSuanQi new];

    double a = [jsq pi];

    NSLog(@"%f", a);

    //冒号的作用是:分隔函数名和参数,否则会分不清0还是10是参数

    int b = [jsq pingFang:10];

    NSLog(@"%d", b);

    int c = [jsq sumWithNum1:10 andNum2:5];

    NSLog(@"%i", c);

    return 0;

}

6、匿名对象

#import <Foundation/Foundation.h>

@interface Car : NSObject

{

    @public

    int speed;

}

- (void)run;

@end


@implementation Car

- (void)run

{

    NSLog(@"速度是%d的车子跑起来了", speed);

}

@end


int main()

{

    //使用指针c1操作这个对象,这个对象是有名对象

    Car* c1 = [Car new];

    Car* c2;

    c2 = [Car new];

    c2->speed = 250;

    [c2 run];

    //下面的类是匿名对象,只要求看懂

    //不要写类似匿名对象这样的代码,会造成内存泄露

    [Car new]->speed = 300;

    [[Car new] run]; 

    return 0;

}

7、编程练习

利用前面的成绩类,重新设计一个学生类

1> 属性

* 姓名

* 学号

* 成绩(包括3科成绩)


2> 行为

* 比较C语言成绩:跟另外一个学生比较C语言成绩,返回成绩差(自己的成绩 -其他人的成绩)

* 比较OC成绩:跟另外一个学生比较OC语言成绩,返回成绩差(自己的成绩 -其他人的成绩)

* 比较iOS成绩:跟另外一个学生比较iOS语言成绩,返回成绩差(自己的成绩 -其他人的成绩)

* 比较总分:跟另外一个学生比较总分,返回成绩差(自己的成绩 -其他人的成绩)

* 比较平均分:跟另外一个学生比较平均分,返回成绩差(自己的成绩 -其他人的成绩)

*/

#import <Foundation/Foundation.h>

@interface Score : NSObject

{

@public

   int CScore;

   int OCScore;

   int IOSScore;

}

- (int) compareCScoreWithOther:(Score *) score;

- (int) compareSumScoreWithOther:(Score *)score;

@end


@implementation Score

- (int) compareCScoreWithOther:(Score *) score

{

   return CScore - score->CScore;

}

- (int) compareSumScoreWithOther:(Score *)score

{

   int sum1 = CScore + OCScore + IOSScore;

   int sum2 = score->CScore + score->OCScore + score->IOSScore;

   return sum1 - sum2;

}

@end


@interface Student : NSObject

{

    @public

   char* name;

   char* number;

    Score* score;

}

- (int) compareCScoreWithOther:(Student*) student;

- (int) compareSumScoreWithOther:(Student*) student;

@end


@implementation Student

- (int) compareCScoreWithOther:(Student*) student

{

   return [score compareCScoreWithOther:student->score];

}

- (int) compareSumScoreWithOther:(Student*) student

{

   return [score compareSumScoreWithOther:student->score];

}

@end


int main()

{

    Student * stu1 = [Student new];

    Student * stu2 = [Student new];

    Score * score1 = [Score new];

    Score * score2 = [Score new];

    

    score1->CScore =100;

    score2->CScore =200;

    stu1->score = score1;

    stu2->score = score2;

    //stu1->score->CScore = 100;//第二层是结构体可以,如果是对象,好像只能间接赋值,如上

    //stu2->score->CScore = 200;

   int a = [stu1 compareCScoreWithOther:stu2];

   int b = [stu1 compareSumScoreWithOther:stu2];

    NSLog(@"%d",a);

   return 0;

}







0 0
原创粉丝点击