zoukankan      html  css  js  c++  java
  • 黑马程序员-OC的类和对象的初步认识

    • OC是面向对象的编程语言,如何创建和使用对象自然是重中之重,对象是怎么产生的呢?创建对象之前必须要有类,他就像要想盖大楼,必须要有图纸,这个图纸就类似于OC中的类

    常用的关键字以及其他英文:

    @interface / @end / @implementation / @public / NSLog(@"") / NSObject
    
    -framework Foundation / Foundation / Foundation.h
    • 和函数一样,类也有声明实现,类的声明里应该包括对象的属性(成员变量)以及对象的行为(方法),其中方法的声明放在类的声明中,其实类的实现就是方法的实现,以下代码就是创建一个类以及通过类创建对象:
     1 //拷贝Foundation框架下的主头文件Foundation.h
     2 //import的作用类似include,区别就是:防止重复拷贝
     3 #import <Foundation/Foundation.h>
     4 
     5 //类的声明
     6 @interface Car : NSObject
     7 {
     8     @public // 让外部的指针能访问成员变量
     9     //实例变量(成员变量)
    10     int wheels; // 轮胎
    11     int speed; // 速度
    12 }
    13 
    14 //对象方法的声明
    15 - (void)run; // 不同于函数的声明: ‘-’ 表明是对象方法,以后还会遇到 ‘+’ ,小括号的作用是用来扩住数据类型
    16 
    17 @end // 类的声明结束标志
    18 
    19 // 类的实现
    20 @implementation Car
    21 
    22 //方法的实现
    23 - (void)run{
    24     
    25     NSLog(@"轮胎有%d个、速度为%d的车子跑起来了", wheels, speed);
    26 }
    27 
    28 @end // 类的实现结束标志
    29 
    30 int main(){
    31     //OC中想要执行一个行为(类的行为以及对象的行为),固定格式为:[行为执行者 行为名称],并且返回的是它在内存中地址
    32     //new是类的一个行为,执行完的结果就是在内存中创建了相应的对象
    33     Car *p = [Car new]; // 执行完这一句,内存中就有一个Car对象,并且指针p指向该对象
    34     
    35     p->wheels = 4;
    36     p->speed = 150;
    37     //因为p指向一个Car对象,所以[p run]执行的是一个对象run方法
    38     [p run];
    39     return 0;
    40 }

    想要成功编译链接这个.m文件,必须这么写:cc xxx.m -framework Foundation,其中xxx为文件名运行结果:

    上述代码的第33行是利用Car类创建了一个Car对象,如果我想再创建一个Car对象呢?依然还是相同的代码,只不过新的对象和之前的对象在内存中是出于不同的位置将上述代码的main函数改为:

     1 int main(){
     2     //OC中想要执行一个行为(类的行为以及对象的行为),固定格式为:[行为执行者 行为名称],并且返回的是它在内存中地址
     3     //new是类的一个行为,执行完的结果就是在内存中创建了相应的对象
     4     Car *p = [Car new]; // 执行完这一句,内存中就有一个Car对象,并且指针p指向该对象
     5     Car *p1 = [Car new];
     6     
     7     p->wheels = 4;
     8     p->speed = 150;
     9     
    10     p1->speed = 200;
    11     p1->wheels = 3;
    12     //因为p指向一个Car对象,所以[p run]执行的是一个对象run方法
    13     [p run];
    14     [p1 run];
    15     
    16     return 0;
    17 }

    该程序的运行结果为

    • 对于第一个程序中的第38行代码系统式如何运行的呢?当程序第一次使用类的时候,内存中会分配一定的空间给类,并且只会加载一次,并且对象的方法会放在类中,并且每次通过类创建一个对象,这个对象中会有一个isa指针指向该类,一旦调用对象的方法(比如这一题的run方法)它会通过isa指针找到类中的对象方法
    • 注意事项:
    1. 类的声明里不能嵌套其他类的声明或者嵌套自己类的实现。代码如下
       1 //错误代码示范:嵌套类的声明
       2 @interface Car :NSObject
       3 
       4 ...
       5 
       6 @interface Person :NSObject
       7 
       8 ...
       9 
      10 @end
      11 
      12 @end
      13 
      14 //错误代码示范:嵌套类的实现
      15 @interface Car :NSObject
      16 
      17 ...
      18 
      19 @implementation Car
      20 
      21 ...
      22 
      23 @end
      24 
      25 @end
    2. 类的所有实例变量要用大括号括起来,对象方法的声明不能放在发括号里,要拿出来。并且不能人为初始化,因为系统会自动初始化所有实例变量(比如int、float等类型初始化为0,指针类型的初始化为nil(类似于C语言中的NULL))
      1 //错误代码示范
      2 @interface Car :NSObject
      3 
      4 {
      5     int speed = 100;
      6     char *name = "MJ";
      7 }
      8 
      9 @end
    3. 关于实例变量的使用:实例变量是对象所独有的,也就是说只有创建了对象才能使用实例变量,并且要想指针访问实例变量,必须在实例变量前加上关键字@public
       1 //错误代码示范
       2 @interface Car :NSObject
       3 
       4 {
       5     int speed;
       6 
       7 }
       8 
       9 ...
      10 
      11 @end
      12 
      13 @implementation Car
      14 
      15 ...
      16 
      17 @end
      18 
      19 int main(){
      20     
      21     speed = 90; // 没有创建对象之前是不能使用实例变量的,即使实例变量前面加了@public
      22     ...
      23 }
    4. 类的声明和实现与main函数的位置问题:和C语言中函数的声明和定义一样,类的声明必须放在main函数前面,类的实现可以放在main函数的后面,不同的是,类的声明不不能省略的
    5. 另外要注意对象方法的声明与之前学过的函数声明的不同之处:对象方法的标志'-'小括号要扩住数据类型例如
      1 - (void)run;
      2 
      3 - (int)eat;
    • 下面将创建一个Person类以及Dog类并且让Person类里有一个Dog实例变量
        1 #import<Foundation/Foundation.h>
        2 
        3 //性别枚举
        4 typedef enum{
        5     SexMan, //
        6     SexWoman //
        7 } Sex;
        8 
        9 //颜色枚举
       10 typedef enum{
       11     ColorBlack, // 黑色
       12     ColorRed, // 红色
       13     ColorYellow //黄色
       14 } Color;
       15 
       16 // 生日结构体
       17 typedef struct{
       18     int year; //
       19     int month; //
       20     int day; //
       21 } Date;
       22 
       23 //Dog类的声明
       24 @interface Dog : NSObject
       25 {
       26     @public
       27     int weight;
       28     Color curColor;
       29 }
       30 
       31 - (void)run; // run方法声明
       32 - (void)eat; // eat方法声明
       33 @end
       34 
       35 //Dog类的实现
       36 @implementation Dog
       37 
       38 - (void)run{
       39     weight -= 1;
       40     NSLog(@"毛色为%d的狗体重减少为:%d", curColor, weight);
       41 }
       42 
       43 - (void)eat{
       44     weight += 1;
       45     NSLog(@"毛色为%d的狗体重增加为:%d", curColor, weight);
       46 }
       47 @end
       48 
       49 // Person类声明
       50 @interface Person : NSObject
       51 {
       52     @public
       53     int age; // 年龄
       54     int weight; // 体重
       55     Sex sex; // 性别
       56     Date birthday; // 生日
       57     Color favColor; // 最喜欢的颜色
       58     Dog *dog;
       59     
       60 }
       61 
       62 - (void)run; // run方法声明
       63 - (void)eat; // eat方法声明
       64 - (void)printf; // printf方法声明
       65 - (void)playWithDog;
       66 - (void)feedDog;
       67 @end
       68 
       69 //Person类实现
       70 @implementation Person
       71 
       72 - (void)run{
       73     weight -= 1;
       74     NSLog(@"年龄为%d的人体重减少为:%d", age, weight);
       75 }
       76 
       77 - (void)eat{
       78     weight += 1;
       79     NSLog(@"年龄为%d的人体重增加为:%d", age, weight);
       80 }
       81 
       82 - (void)printf{
       83     NSLog(@"体重为%d-年龄为%d-性别为%d-最爱的颜色为%d-生日为%d/%d/%d", weight, age, sex, favColor, birthday.year, birthday.month, birthday.day);
       84 }
       85 
       86 - (void)playWithDog{
       87     [dog run];
       88 }
       89 
       90 - (void)feedDog{
       91     [dog eat];
       92 }
       93 @end
       94 
       95 int main(){
       96     //创建Person对象
       97     Person *p = [Person new];
       98     
       99     //初始化Person对象实例变量
      100     p->age = 24;
      101     p->weight = 60;
      102     p->sex = SexMan;
      103     p->favColor = ColorYellow;
      104     Date d = {2000,4,5}; // 初始化结构体Date变量d
      105     p->birthday = d;
      106     
      107     //创建Dog对象
      108     Dog *dog = [Dog new];
      109     p->dog = dog;
      110     
      111     //初始化Dog对象实例变量
      112     dog->weight = 15;
      113     dog->curColor = ColorRed;
      114     
      115     [p playWithDog]; // 调用Person对象的playWithDog方法
      116     [p playWithDog];
      117     [p playWithDog];
      118     [p feedDog];
      119     
      120     [p run]; // 调用Person类的run方法
      121     [p run];
      122     [p run];
      123     
      124     [p eat]; // 调用Person类的eat方法
      125     [p printf]; // 调用Person类的printf方法
      126     
      127     return 0;
      128     
      129 }

      (也不知道代码能不能想C那样分成多个文件)这样在一个.m文件写下去的话,肯定会让人崩溃的。在写这一段代码中我犯了如下错误:

    1. @public漏写
    2. 将Dog类的声明写在了Person类声明的后面,这样会导致编译链接的时候会警告Dog *dog没有定义(估计等学到了多文件开发的时候这个问题就能避免了)
    3. 漏写了上述代码的第109行,这样会导致Person对象中的dog成员变量指向nil(空),进一步导致第115-118行的所有代码无效
  • 相关阅读:
    js预编译
    JS防抖和节流模式的实际应用
    常见的几种数组去重的方法,总有一种适合你~
    调用微信扫一扫功能,踩坑'invalid signature'
    如何快速的vue init 属于自己的vue模板?
    如何做到在webpack打包vue项目后,在外部动态修改配置文件
    vue拖拽组件 vuedraggable API options实现盒子之间相互拖拽排序克隆clone
    js解析URL参数
    vue复选框 模拟checkbox多选全选,vue页面加载屏蔽花括号
    js毫秒转换天时分秒/动态倒计时
  • 原文地址:https://www.cnblogs.com/oucding/p/4414299.html
Copyright © 2011-2022 走看看