zoukankan      html  css  js  c++  java
  • OC语言的面向对象—类和对象、方法

    1、 面向对象和面向过程思想

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

    1. 面向对象和面向过程的区别
    1) 用电脑听歌为例子
    a) 面向过程
    ➢ 打开电脑
    ➢ 播放电脑中的歌曲
    ➢ 关闭电脑

     

    b) 面向对象(不是相亲的“对象”)
    ➢ 电脑   
    ◇ 开机   
    ◇ 播放歌曲   
    ◇ 关机

     

    2) 区别分析
    ➢ 面向过程关注的是解决问题需要哪些步骤;面向对象关注的是解决问题需要哪些对象
    ➢ 没有开发经验很难感受到它们的区别,两种思想都能达到解决问题的目的,但是解决思路不一样

     

    2. 现实生活中面向对象的例子
    ➢ 想打电话发短信 à 找手机,不用分析电话要怎样才能拨通
    ➢ 去饭店吃饭 à 找服务员,不用分析怎么到厨房炒菜
    ➢ 汽车坏了 à 找汽车维修工,不用分析修车的步骤
    ➢ 境界:万物皆对象

     

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

     

    2、 类和对象的关系

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

    1. 如何创建对象
    1) 面向对象解决问题的时候必须有对象,那如何创建对象呢?

     

    2) 现实生活的例子:如何创造汽车对象
    a) 需要先有汽车建造图纸图纸上描述清楚汽车应该具备的属性和功能(行为)
    ➢ 属性轮子数、时速
    ➢ 功能(行为
    b) 然后再根据图纸上的描述生成汽车
    c) 每一辆汽车都是对象,都有自己具体的属性值,都是图纸的实例
    d) 图纸是抽象的,房子是具体的。图纸是对房子对象的高度概括

     

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

     

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

     

    2) 一般名词都是类
    ➢ 坦克发射3颗炮弹轰掉2架飞机
    ➢ 小明在公车上牵着一条叼着热狗的狗
     
    3) 哪个对象最清楚这个行为,就把这个行为写到哪个对象中去。打开电脑(开机)这个行为应该是属于电脑的。
     
     
     
    1、 定义OC的类和创建OC对象
    ➢ 接下来就在OC中模拟现实生活中的情况,创建一辆车出来。首先要有一个车子类,然后再利用车子类创建车子对象
    ➢ 要描述OC中的类稍微麻烦一点,分2大步骤:类的声明类的实现(定义)。跟函数类似,函数有分声明和定义
    1. 类的声明
    1) 代码编写
    ➢ 定义一个Car,拥有2个属性:轮子数、时速1个行为:跑
    ➢ 类名属性的命名规则:标示符的规则
    ➢ 类名的命名规范有意义、驼峰标识、首字母大写

    #import <Foundation/Foundation.h>

    // 类的声明

    @interface Car : NSObject

    {

       @public

       int wheels// 多少个轮子

       int speed// 时速

    }

    - (void)run; // 跑的行为

    @end

     

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

     

    3) @public

    @public可以Car对象的wheelsspeed属性被外界访问

     

    4) NSObject

    加上:NSObject的目的是让Car类具备创建对象的能力

     

    2. 的实现

    // 类的实现

    @implementation Car

    - (voidrun

    {

       NSLog(@"%i个轮子%i时速车子跑起来了"wheelsspeed);

    }

    @end

     

    3. 创建对象
    1) 代码编写

    // 主函数

    int main()

    {

       // 创建车子对象

       Car *c = [Car new];

       c->wheels = 3;

       c->speed = 300;

       

       [c run];

       return 0;

    }

    常见错误

    (1)@interface  @end和@implementation  @end不能嵌套包含

    (2)只有类的声明没有类的实现

    (3)漏写@end

    (4)两个类的声明嵌套(可以把顺序打乱)

    (5)成员变量没有写在{}里

    (6)方法的声明写在了{}里面

    (7)在声明时对类的成员变量进行初始化,请注意成员变量不能脱离对象而独立存在

    (8)方法无法像函数那样的调用

    (9)成员变量和方法不能用static等关键字修饰,不要和c语言混淆

    (10)类的实现可以写在mian函数后面,在使用之前只要有声明就可以

     

    2) main函数的代码分析、内存分析(对象在内存中有成员)
    ➢ [Car new]每次都会创建出新的对象,并且返回对象的地址,那么就应该用一个指针变量保存对象的地址

    Car *c = [Car new];

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

    ➢ 设置车子对象的属性

    跟用指向结构体的指针访问结构体属性一样,用->

    c->wheels = 3;

    c->speed = 300;

     

     

    4. 创建多个Car对象
    ➢ 分别只设置wheelsspeed属性

    Car *c1 = [Car new];

    c1->wheels = 4;

    Car *c2 = [Car new];

    c2->speed = 250;

    [c1 run];

    ➢ 1个赋值给另一个,然后修改属性

    Car *c1 = [Car new];

    c1->wheels = 4;

    c1->speed = 250;

    Car *c2 = c1;

    c2->wheels = 3;

    [c1 run];

     

    5. 面向对象封装的好处
    ➢ 更加接近人类的思考方式
    ➢ 只需要关注对象,不需要关注步骤

     

    6. 对象与函数参数
    ➢ 对象成员变量作为函数参数
    ➢ 指向对象的指针作为函数参数
    ◆ 修改指向指向对象成员
    ◆ 修改指针的指向

     

    2、 类的声明和实现
    1. @interface和@implementation的分工
     
    ◆ @interface就好像暴露在外面时钟表面
    ◆ @implementation就好像隐藏在时钟内部的构造实现

     

    2. 声明和定义多个类

     

     

    3. 常见错误
    ● 只有类的声明,没有类的实现
    ● 漏了@end
    ● @interface和@implementation嵌套
    ● 两个类的声明嵌套
    ● 成员变量没有写在括号里面
    ● 方法的声明写在了大括号里面

     

    4. 语法细节
    ● 成员变量不能在{}中进行初始化、不能被直接拿出去访问
    ● 方法不能当做函数一样调用
    ● 成员变量方法不能用static等关键字修饰,别跟C语言混在一起(暂时忽略)
    ● 类的实现可用写在main函数的后面,主要在声明后面就行了

     

    5. OC方法和函数的区别
    ● OC方法只能声明在@interface@end之间,只能实现在@implementation@end之间。也就是说OC方法不能独立于类存在
    ● C函数不属于类,跟类没有联系,C函数只归定义函数的文件所有
    ● C函数不能访问OC对象的成员
    ● 低级错误:方法有声明,但是实现的时候写成了函数

     

    6. OC的方法注意
    ● 方法只有声明,没有实现(经典错误)
    ● 方法没有声明,只有实现(编译器警告,但是能调用,OC的弱语法)
    ● 编译的时候:访问没有的成员变量直接报错,访问没有的方法,只是警告

     

    7. @implementation
    ➢ 没有@interface,只有@implementation,也是能成功定义一个类的

    @implementation Car : NSObject

    {

       @public

       int wheels// 多少个轮子

       int speed// 时速

    }

    - (voidrun

    {

       NSLog(@"%i个轮子%i时速车子跑起来了"wheelsspeed);

    }

    @end

    ➢ @implementation中不能声明和@interface一样的成员变量
     

     小结: OC对象与函数有着本质的区别:

    (1)方法的实现只能写在@implementation··@end中,对象方法的声明只能写在@interface···@end中间

    (2)对象方法都以-号开头,类方法都以+号开头

    (3)对象方法只能由对象来调用,类方法只能由类来调用,不能当做函数一样调用

    (4)函数属于整个文件,可以写在文件中的任何位置,包括@implementation··@end中,但写在@interface···@end会无法识别,函数的声明可以再main函数内部也可以在main函数外部。

    (5)对象方法归类对象所有

    (6)函数调用不依赖与对象

    (7)函数内部不能直接通过成员变量名访问对象的成员变量

     

    (一)对象方法

    (1)对象方法以-开头如 -(void)xx;

    (2)对象方法只能又对象来调用

    (3)对象方法中可以访问当前对象的成员变量

    (4)调用格式   [对象名  对象方法名];

    二)类方法

    (1)类方法以+开头  如+(void)put;

    (2)类方法只能由类来调用

    (3)类方法中不能访问实例(成员)变量,因为类方法又类来调用,并没有创建存储空间来存储类中的成员变量。

    (4)调用格式:[类名  类方法名];

    (5)类方法的好处和适用场合:

    不依赖于对象,执行效率更高;

    能用类方法解决的问题,尽量使用类方法;

    场合:当方法内部不需要使用到成员变量时,可以改为类方法。

    三)文件编译

    在工作中,通常把不同的类放到不同的文件中,每个类的声明和实现分开,声明写在.h头文件中,实现写在相应的.m文件中去,类名是什么,文件名的前缀就是什么。

    假设有两个类,分别是Person类和Dog类,则通常有下面五个文件:

    (1)Person.h    Person类的声明文件

    (2)Person.m    Person类的实现文件

    (3)Dog.h Dog类的声明文件

    (4)Dog.m Dog类的实现文件

    (5)Main.m 主函数(程序入口)

    在主函数以及类的实现文件中要使用#import包含相应的头文件。

    补充:import有两个作用:一是和include一样,完完全全的拷贝文件的内容;二是可以自动防止文件内容的重复拷贝(即使文件被多次包含,也只拷贝一份)。

    在使用命令行进行编译链接文件的时候,通常是把.m文件单文件编译,然后再把所有的目标文件链接,但是在Xcode中,是把所有的.m文件都进行编译链接的,如果出现重复定义的错误,那大部分问题根源应该就是文件内容被重复包含或者是包含.m文件所引起的。

    源文件中不论是使用include还是import,都不能包含.m或者是.c文件,只能放声明。因此,在OC中通常把类拆分开来,拆分成声明和实现两个部分。

    提示:这也是编程思想的一种体现,可以说.h和.m文件时完全独立的,只是为了要求有较好的可读性,才要求两个文件的文件名一致,这也是把接口和实现分离,让调用者不必去关心具体的实现细节。

    Xcode是写一行编译一行,有简单的修复功能,红色是错误提示,黄色警告。如果在程序中声明了一个变量,但是这个变量没有被使用也会产生警告信息。在调试程序的时候,如果发现整个页面都没有报错,但是一运行就错误,那么一定是链接报错。

     

    3、 方法

    设计一个Caculator计算器类,它拥有计算的功能(行为)

    1. 不带参数的方法
    ◆ 设计一个返回PI的方法

    // 方法声明

    - (double)pi;

    // 方法实现

    - (double)pi

    {

       return 3.14;

    }

     
    2. 带一个参数的方法
    ◆ 设计一个计算平方的方法

    // 方法声明

    - (double)square:(double)number;

    // 方法实现

    - (double)square:(double)number

    {

       return number * number;

    }

     

     
    3. 带多个参数的方法
    ◆ 设计一个计算和的方法

    // 方法声明

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

    // 方法实现

    - (double)sumOfNum1:(double)num1 andNum2:(double)num2

    {

       return num1 + num2;

    }

     

    4. 方法名注意
    ● 冒号也是方法名的一部分
    ● 同一个类中不允许两个对象方法同名

     

    5. 习题
     1 #import <Foundation/Foundation.h>
     2 /*
     3  对象方法
     4  1> 减号 - 开头
     5  2> 只能由对象来调用
     6  3> 对象方法中能访问当前对象的成员变量(实例变量)
     7  
     8  类方法
     9  1> 加号 + 开头
    10  2> 只能由类(名)来调用
    11  3> 类方法中不能访问成员变量(实例变量)
    12  
    13  
    14  类方法的好处和使用场合
    15  1> 不依赖于对象,执行效率高
    16  2> 能用类方法,尽量用类方法
    17  3> 场合:当方法内部不需要使用到成员变量时,就可以改为类方法
    18  
    19  可以允许类方法和对象方法同名
    20  */
    21 
    22 
    23 @interface Person : NSObject
    24 {
    25     int age;
    26 }
    27 
    28 // 类方法都是以+开头
    29 + (void)printClassName;
    30 
    31 - (void)test;
    32 + (void)test;
    33 
    34 @end
    35 
    36 @implementation Person
    37 
    38 + (void)printClassName
    39 {
    40     // error:instance variable 'age' accessed in class method
    41     // 实例变量age不能在类方法中访问
    42     //NSLog(@"这个类叫做Person-%d", age);
    43 }
    44 
    45 - (void)test
    46 {
    47     NSLog(@"111-%d", age);
    48     
    49     //[Person test];
    50 }
    51 
    52 + (void)test
    53 {
    54     // 会引发死循环
    55     //[Person test];
    56     
    57     NSLog(@"333");
    58     
    59     // 会引发死循环
    60     //    /[Person test];
    61 }
    62 
    63 @end
    64 
    65 int main()
    66 {
    67     //[Person printClassName];
    68     
    69     [Person test];
    70     
    71     //Person *p = [Person new];
    72     //[p test];
    73     
    74     /*
    75      -[Person printClassName]: unrecognized selector sent to instance 0x7fa520c0b370
    76      */
    77     // 系统会认为现在调用的printClassName是个对象方法
    78     //[p printClassName];
    79     
    80     return 0;
    81 }

     

     

    4、 匿名对
    ● 属性访问

    [Car  new]->speed = 200;

    ● 方法调用

    [ [Car  new]  run];

     
    5、练习

     

     1 /*
     2  类名:Car
     3  属性:轮胎个数、时速(速度)
     4  行为:跑
     5  */
     6 
     7 // 因为使用了NSObject
     8 #import <Foundation/Foundation.h>
     9 
    10 // 完整地写一个函数:函数的声明和定义(实现)
    11 // 完整地写一个类:类的声明和实现
    12 
    13 // 1.类的声明
    14 // 声明对象的属性、行为
    15 // : NSObject 目的是:让Car这个类具备创建对象的能力
    16 @interface Car : NSObject
    17 {// 用来声明对象属性(实例变量成员变量,默认会初始化为0)
    18     // @public可以让外部的指针间接访问对象内部的成员变量
    19     @public
    20     int wheels; // 轮胎个数
    21     int speed; // 时速(xxkm/h)
    22 }
    23 
    24 // 方法(行为):方法名、参数、返回值(声明、实现)
    25 // 只要是OC对象的方法,必须以减号 - 开头
    26 // OC方法中任何数据类型都必须用小括号()扩住
    27 // OC方法中的小括号():括住数据类型
    28 - (void)run;
    29 
    30 @end
    31 
    32 // 2.类的实现
    33 // 用来实现@inteface中声明的方法
    34 @implementation Car
    35 // 方法的实现(说清楚方法里面有什么代码)
    36 
    37 - (void)run
    38 {
    39     NSLog(@"车子跑起来了");
    40 }
    41 
    42 @end
    43 
    44 int main()
    45 {
    46     // 在OC中,想执行一些行为,就写上一个中括号[行为执行者 行为名称]
    47     // 利用类来创建对象
    48     // 执行了Car这个类的new行为来创建新对象
    49     
    50     // 定义了一个指针变量p,p将来指向的是Car类型的对象
    51     // [Car new]每次都会创建出一个新对象,并且会返回新对象本身(新对象的地址)
    52     Car *p = [Car new];
    53     
    54     
    55     Car *p2 = [Car new];
    56     p2->wheels = 5;
    57     p2->speed = 300;
    58     [p2 run];
    59     
    60     // 给p所指向对象的wheels属性赋值
    61     p->wheels = 4;
    62     p->speed = 250;
    63     
    64     // 给p所指向对象发送一条run消息
    65     [p run];
    66     
    67     NSLog(@"车子有%d个轮子,时速位:%dkm/h", p->wheels, p2->speed);
    68     
    69     return 0;
    70 }
     
     1 /*
     2  3  类名:Person
     4  属性(成员变量实例变量):体重、年龄
     5  行为(方法):走路、吃
     6  */
     7 #import <Foundation/Foundation.h>
     8 /*
     9  1.类的声明
    10  * 成员变量
    11  * 方法的声明
    12  */
    13 @interface Person : NSObject
    14 {
    15 @public
    16     int age;
    17     double weight;
    18 }
    19 
    20 - (void)walk;
    21 - (void)eat;
    22 
    23 @end
    24 
    25 
    26 // 2.类的实现
    27 @implementation Person
    28 
    29 // 实现@interface中声明的方法
    30 - (void)walk
    31 {
    32     NSLog(@"%d岁、%f公斤的人走了一段路", age, weight);
    33 }
    34 
    35 - (void)eat
    36 {
    37     NSLog(@"%d岁、%f公斤的人在吃东西", age, weight);
    38 }
    39 
    40 @end
    41 
    42 int main()
    43 {
    44     // 在使用类创建对象之前,会将类加载进内存
    45     Person *p = [Person new];
    46     p->age = 20;
    47     p->weight = 40;
    48     
    49     [p eat];
    50     [p walk];
    51     
    52     Person *p2 = [Person new];
    53     p2->age = 30;
    54     p2->weight = 60;
    55     [p2 eat];
    56     [p2 walk];
    57     
    58     /*
    59      Person *p2 = [Person new];
    60      p2->age = 30;
    61      p2->weight = 50;
    62      
    63      p = p2;
    64      
    65      p->age = 40;
    66      
    67      [p2 walk];
    68      */
    69     
    70     /*
    71      Person *p = [Person new];
    72      p->age = 20;
    73      
    74      Person *p2 = [Person new];
    75      p2->weight = 50.0;
    76      
    77      [p walk];
    78      */
    79     
    80     /*
    81      Person *p = [Person new];
    82      p->age = 20;
    83      p->weight = 50.0;
    84      [p walk];
    85      
    86      Person *p2 = [Person new];
    87      p2->age = 30;
    88      p2->weight = 60.0;
    89      [p2 walk];
    90      */
    91     return 0;
    92 }

     

     

  • 相关阅读:
    20201112 装饰器之函数即变量
    2月13日:毕业设计进度
    2月12日:毕业设计进度
    2月11日:毕业设计进度
    2月10日:毕业设计进度
    2月9日:毕业设计进度
    2月8日:毕业设计进度
    2月7日:毕业设计进度
    2月6日:毕业设计进度
    2月5日:毕业设计进度
  • 原文地址:https://www.cnblogs.com/zhangxiaomeng1991/p/4159180.html
Copyright © 2011-2022 走看看