zoukankan      html  css  js  c++  java
  • OC面向对象的三大特性

     

    一、面向对象的三大特性:封装(成员变量)、继承和多态
    1、 set方法和get方法
    1. set方法和get方法的使用场合

    @public的成员可以被随意赋值,应该使用set方法和get方法来管理成员的访问(类似机场的安检、水龙头过滤,过滤掉不合理的东西,比如僵尸的生命值不能为负数

    2. set方法
    1) 作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值
    2) 命名规范:
    ➢ 方法都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写
    ➢ 形参名称不要跟成员变量同名
    3. get方法
    1) 作用:返回对象内部的成员变量
    2) 命名规范:get方法的名称一般就跟成员变量同名
    4. 成员变量的命名规范
    ➢ 成员变量都以下划线 _ 开头
    ➢ 可以跟get方法的名称区分开
    ➢ 可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量
    5. 代码示例

    #import <Foundation/Foundation.h>

    // 声明

    @interface Car : NSObject

    {

       int _wheels; // 轮子个数

    }

    /*set方法*/

    - (void) setWheels:(int)wheels;

    /*get方法*/

    - (int) wheels;

    @end

     

    @implementation Car

    // set方法的实现

    - (void) setWheels:(int)wheels

    {

       // 对外面传进来的轮子数进行过滤

       if (wheels<=0)

       {

           wheels = 1;

       }

       

       _wheels = wheels;

    }

     

    // get方法的实现

    - (int) wheels

    {

       return _wheels;

    }

    @end

    6. 封装的好处
    ➢ 过滤不合理的值
    ➢ 屏蔽内部的赋值过程
    ➢ 让外界不必关注内部的细节
     
     1 /**
     2  4.设计Car类
     3  1> 属性
     4  * 速度
     5  
     6  2> 方法
     7  * 属性相应的set和get方法
     8  * 一个对象方法跟其他车子比较车速,返回速度差
     9  * 一个类方法比较两辆车的车速,返回速度差
    10  */
    11 
    12 #import <Foundation/Foundation.h>
    13 
    14 //
    15 @interface Car : NSObject
    16 {
    17     int _speed; // 速度
    18 }
    19 
    20 // 速度的getter和setter
    21 - (void)setSpeed:(int)speed;
    22 - (int)speed;
    23 
    24 // 跟其他车子比较车速,返回速度差
    25 - (int)compareSpeedWithOther:(Car *)car;
    26 // 比较两辆车的车速,返回速度差
    27 + (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car2;
    28 @end
    29 
    30 @implementation Car
    31 // 速度的getter和setter
    32 - (void)setSpeed:(int)speed
    33 {
    34     _speed = speed;
    35 }
    36 - (int)speed
    37 {
    38     return _speed;
    39 }
    40 
    41 // 跟其他车子比较车速,返回速度差
    42 - (int)compareSpeedWithOther:(Car *)car
    43 {
    44     // 第1种思路
    45     // return _speed - [car speed];
    46     
    47     // 第2种思路
    48     return [Car compareSpeedBetweenCar1:self andCar2:car];
    49 }
    50 
    51 // 比较两辆车的车速,返回速度差
    52 + (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car2
    53 {
    54     return [car1 speed] - [car2 speed];
    55 }
    56 @end
    2、 类方法
    1. 基本概念

    直接可以用类名来执行的方法类本身会在内存中占据存储空间,里面有类对象方法列表

    2. 类方法和对象方法对比
    1) 对象方法
    ➢ 以减号-开头
    ➢ 只能让对象调用,没有对象,这个方法根本不可能被执行
    ➢ 对象方法能访问实例变量(成员变量)

     

    2) 方法
    ➢ 以加号+开头
    ➢ 只能用类名调用,对象不能调用
    ➢ 类方法中不能访问实例变量(成员变量)
    ➢ 使用场合:当不需要访问成员变量的时候,尽量用类方法
    3) 类方法和对象方法可以同名
     
    3、 self关键字
    1. 成员变量和局部变量同名
    ➢ 当成员变量和局部变量同名时,采取就近原则,访问的是局部变量
    ➢ self访问成员变量,区分同名的局部变量
    2. 使用细节
    1) 出现的地方:所有的OC方法中(对象方法类方法),不能出现在函数
    2) 作用
    ➢ 使用 "self->成员变量名访问当前方法调用的成员变量
    ➢ 使用 "[self 方法名];" 来调用方法(对象方法类方法)
    3. 常见错误
    ➢ 低级错误:用self去调用函数
    ➢ 类方法中self调用对象方法,对象方法中用self调用类方法
    ➢ self死循环
     

    练习:设计一个成绩类

     * C语言成绩(可读可写)

     * OC成绩(可读可写)

     * 总分(只读)

     * 平均分(只读)

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface Score : NSObject
     4 {
     5     int _cScore; // C语言成绩
     6     int _ocScore; // OC成绩
     7     
     8     int _totalScore;// 总分
     9     int _averageScoe; // 平均分
    10 }
    11 
    12 - (void)setCScore:(int)cScore;
    13 - (int)cScore;
    14 
    15 - (void)setOcScore:(int)ocScore;
    16 - (int)ocScore;
    17 
    18 - (int)totalScore;
    19 - (int)averageScore;
    20 
    21 @end
    22 
    23 @implementation Score
    24 - (void)setCScore:(int)cScore
    25 {
    26     _cScore = cScore;
    27     
    28     // 计算总分
    29     _totalScore = _cScore + _ocScore;
    30     _averageScoe = _totalScore/2;
    31 }
    32 - (int)cScore
    33 {
    34     return _cScore;
    35 }
    36 
    37 - (void)setOcScore:(int)ocScore
    38 {
    39     _ocScore = ocScore;
    40     
    41     // 计算总分
    42     _totalScore = _cScore + _ocScore;
    43     _averageScoe = _totalScore/2;
    44 }
    45 // 监听成员变量的改变
    46 
    47 - (int)ocScore
    48 {
    49     return _ocScore;
    50 }
    51 
    52 - (int)totalScore
    53 {
    54     return _totalScore;
    55 }
    56 - (int)averageScore
    57 {
    58     return _averageScoe;
    59 }
    60 @end
    61 
    62 
    63 int main()
    64 {
    65     Score *s = [Score new];
    66     
    67     [s setCScore:90];
    68     [s setOcScore:100];
    69     
    70     [s setCScore:80];
    71     
    72     
    73     int a = [s totalScore];
    74     
    75     NSLog(@"总分:%d", a);
    76     
    二、 继承
    1. 继承的基本用法
    ● 设计两个类BirdDog

    // Bird的声明

    @interface Bird : NSObject

    {

       @public

       int weight;

    }

    - (void)eat;

    @end

    // Bird定义

    @implementation Bird

    - (void)eat {

       NSLog(@"吃吃吃-体重:%d", weight);

    }

    @end

    // Dog声明

    @interface Dog : NSObject

    {

       @public

       int weight;

    }

    - (void)eat;

    @end

    // Dog的定义

    @implementation Dog

    - (void)eat {

       NSLog(@"吃吃吃-体重:%d", weight);

    }

    @end

    ● 有相同的属性和行为,抽出一个父类Animal(先抽取weight属性,再抽取eat方法)

    // Animal的声明

    @interface Animal : NSObject

    {

       @public

           int weight;

    }

    - (void)eat;

    @end

    // Animal的定义

    @implementation Animal

    - (void)eat {

       NSLog(@"吃吃吃-体重:%d", weight);

    }

    @end

    ● 子类在父类的基础上拓充属性和方法

    // Bird的声明

    @interface Bird : Animal

    {

       @public

           int height;

    }

    - (void)fly;

    @end

     

    // Bird的定义

    @implementation Bird

    - (void)fly {

       NSLog(@"飞飞飞-高度:%d", height);

    }

    @end

     

    // Dog的声明

    @interface Dog : Animal

    {

       @public

           int speed;

    }

    - (void)run;

    @end

    // Dog的定义

    @implementation Dog

    - (void)run {

       NSLog(@"跑跑跑-高度:%d", speed);

    }

    @end

    ● 子类方法和属性的访问过程:如果子类没有,就去访问父类的
    ● 父类被继承了还是能照常使用的
    ● 父类的静态方法
    ● 画继承结构图,从子类抽取到父类
    ● NSObject的引出:全部OC类的最终父类,包含了一些常用方法,比如+new

     

    2. 继承的专业术语
    ● 父类超类  superclass
    ● 子类  subclasssubclasses

     

    3. 继承的细节
    ● 单继承
    ● 子类和父类不能有相同的成员变量
    ● 方法的重写

     

    4. super关键字
    ● 分别调用父类的对象方法和类方法

       在子类中重写方法时,可以让调用者跳过这一层而调用父类中的方法。

     

     1 /*
     2  僵尸
     3  
     4  跳跃僵尸、舞王僵尸、铁桶僵尸
     5  */
     6 #import <Foundation/Foundation.h>
     7 
     8 /*
     9  super的作用
    10  1.直接调用父类中的某个方法
    11  2.super处在对象方法中,那么就会调用父类的对象方法
    12  super处在类方法中,那么就会调用父类的类方法
    13  
    14  3.使用场合:子类重写父类的方法时想保留父类的一些行为
    15  */
    16 
    17 // 僵尸
    18 @interface Zoombie : NSObject
    19 - (void)walk;
    20 
    21 + (void)test;
    22 - (void)test;
    23 
    24 @end
    25 
    26 @implementation Zoombie
    27 - (void)walk
    28 {
    29     NSLog(@"往前挪两步******");
    30 }
    31 
    32 + (void)test
    33 {
    34     NSLog(@"Zoombie+test");
    35 }
    36 
    37 - (void)test
    38 {
    39     NSLog(@"Zoombie-test");
    40 }
    41 @end
    42 
    43 // 跳跃僵尸
    44 @interface JumpZoombie : Zoombie
    45 + (void)haha;
    46 - (void)haha2;
    47 @end
    48 
    49 
    50 @implementation JumpZoombie
    51 
    52 + (void)haha
    53 {
    54     [super test];
    55 }
    56 
    57 - (void)haha2
    58 {
    59     [super test];
    60 }
    61 
    62 - (void)walk
    63 {
    64     // 跳两下
    65     NSLog(@"跳两下");
    66     
    67     // 走两下(直接调用父类的walk方法)
    68     [super walk];
    69     //NSLog(@"往前挪两步----");
    70     
    71 }
    72 @end
    73 
    74 int main()
    75 {
    76     //[JumpZoombie haha];
    77     JumpZoombie *jz = [JumpZoombie new];
    78     
    79     [jz walk];
    80     
    81     return 0;
    82 }

     5. 继承的好处

    ● 不改变原来模型的基础上,拓充方法
    ● 建立了类与类之间的联系
    ● 抽取了公共代码
    ● 坏处:耦合性强

     

    6. 继承的使用场合
    ● 它的所有属性都是你想要的,一般就继承
    ● 它的部分属性是你想要的,可以抽取出另一个父类
    继承的使用场合练习

     1> 当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中

     2> 当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类

     A

     {

        int _age;

        int _no;

     }

     B : A

     {

        int _weight;

     }

     // 继承:xx 是 xxx

     // 组合:xxx 拥有 xxx

     2.组合

     A

     {

         int _age;

         int _no;

     }

     B

     {

         A *_a;

         int _weight;

     }

     
     1 #import <Foundation/Foundation.h>
     2 /*
     3  1.继承的好处:
     4  1> 抽取重复代码
     5  2> 建立了类之间的关系
     6  3> 子类可以拥有父类中的所有成员变量和方法
     7  
     8  2.注意点
     9  1> 基本上所有类的根类是NSObject
    10  */
    11 
    12 
    13 /********Animal的声明*******/
    14 @interface Animal : NSObject
    15 {
    16     int _age;
    17     double _weight;
    18 }
    19 
    20 - (void)setAge:(int)age;
    21 - (int)age;
    22 
    23 - (void)setWeight:(double)weight;
    24 - (double)weight;
    25 @end
    26 
    27 /********Animal的实现*******/
    28 @implementation Animal
    29 - (void)setAge:(int)age
    30 {
    31     _age = age;
    32 }
    33 - (int)age
    34 {
    35     return _age;
    36 }
    37 
    38 - (void)setWeight:(double)weight
    39 {
    40     _weight = weight;
    41 }
    42 - (double)weight
    43 {
    44     return _weight;
    45 }
    46 @end
    47 
    48 /********Dog*******/
    49 // : Animal 继承了Animal,相当于拥有了Animal里面的所有成员变量和方法
    50 // Animal称为Dog的父类
    51 // Dog称为Animal的子类
    52 @interface Dog : Animal
    53 @end
    54 
    55 @implementation Dog
    56 @end
    57 
    58 /********Cat*******/
    59 @interface Cat : Animal
    60 @end
    61 
    62 @implementation Cat
    63 @end
    64 
    65 int main()
    66 {
    67     Dog *d = [Dog new];
    68     
    69     [d setAge:10];
    70     
    71     NSLog(@"age=%d", [d age]);
    72     return 0;
    73 }

     

    三、多态
     
    1. 多态的基本概念
    ● 某一类事物的多种形态,必须要有继承,没有继承就没有多态。
    ● OC对象具有多态性,多态在代码中的体现即父类指针指向子类对象。

     

    2. 多态的体现

    Person *p = [Student new];

    p->age = 100;

    [p walk];

    ● 子类对象赋值给父类指针
    ● 父类指针访问对应的属性和方法

     

    3. 多态的好处
    ● 用父类接收参数,节省代码

     

    4. 多态的局限性
    ● 不能访问子类的属性(可以考虑强制转换)

     

    5. 多态的细节
    ● 动态绑定:在运行时根据对象的类型确定动态调用的方法
     

    多态使用总结

     1.没有继承就没有多态

     2.代码的体现:父类类型的指针指向子类对象

     3.好处:如果函数方法参数中使用的是父类类型,可以传入父类、子类对象

     4.局限性: 父类类型的变量不能直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法

     1 #import <Foundation/Foundation.h>
     2 // 动物
     3 @interface Animal : NSObject
     4 - (void)eat;
     5 @end
     6 
     7 @implementation Animal
     8 - (void)eat
     9 {
    10     NSLog(@"Animal-吃东西----");
    11 }
    12 @end
    13 
    14 //
    15 @interface Dog : Animal
    16 - (void)run;
    17 @end
    18 
    19 @implementation  Dog
    20 - (void)run
    21 {
    22     NSLog(@"Dog---跑起来");
    23 }
    24 - (void)eat
    25 {
    26     NSLog(@"Dog-吃东西----");
    27 }
    28 @end
    29 
    30 //
    31 @interface Cat : Animal
    32 
    33 @end
    34 
    35 @implementation Cat
    36 - (void)eat
    37 {
    38     NSLog(@"Cat-吃东西----");
    39 }
    40 @end
    41 
    42 // 这个函数是专门用来喂动画
    43 //void feed(Dog *d)
    44 //{
    45 //    [d eat];
    46 //}
    47 //
    48 //void feed2(Cat *c)
    49 //{
    50 //    [c eat];
    51 //}
    52 //
    53 
    54 // 如果参数中使用的是父类类型,可以传入父类、子类对象
    55 void feed(Animal *a)
    56 {
    57     [a eat];
    58 }
    59 
    60 int main()
    61 {
    62     // 多态的局限性:父类类型的变量 不能 用来调用子类的方法
    63     Animal *aa = [Animal new];
    64      feed(aa);
    65      
    66      Dog *dd = [Dog new];
    67      feed(dd);
    68      
    69      Cat *cc = [Cat new];
    70      feed(cc);
    71      
    72     
    73      // NSString *s = [Cat new];
    74      Animal *c = [Cat new];
    75      
    76      
    77      NSObject *n = [Dog new];
    78      NSObject *n2 = [Animal new];
    79     
    80      
    81       //多种形态
    82      Dog *d = [Dog new]; // Dog类型
    83     
    84      //多态:父类指针指向子类对象
    85      Animal *a = [Dog new];
    86      
    87      // 调用方法时会检测对象的真实形象
    88      [a eat];
    89     
    90     return 0;
    91 }
    3、 NSString的简单使用
     
    1. 字符串的快速创建

    NSStirng *str = @Hello;

    2. 使用静态方法创建
    3. 使用%@输出字符串

    NSString *name = @mj;

    NSLog(@我的名字是%@,  name);

     

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface Person : NSObject
     4 {
     5     //char *_name;
     6     NSString *_name;
     7 }
     8 @end
     9 
    10 int main()
    11 {
    12     /*
    13      // 最简单的创建字符串的方式
    14      NSString *str = @"itcast";
    15      
    16      char *name = "itcast";
    17      
    18      
    19      NSLog(@"我在%@上课", str);
    20      //NSLog(@"%s", name);
    21      */
    22     
    23     int age = 15;
    24     int no = 5;
    25     NSString *name = @"哈哈jack";
    26     // length方法算的是字数
    27     int size = [name length];
    28     
    29     NSLog(@"%d", size);
    30     
    31     // 创建OC字符串的另一种方式
    32     NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d and name is %@", age, no, name];
    33     
    34     
    35     NSLog(@"---- %ld", [newStr length]);
    36     
    37     return 0;
    38 }

    作业

      1 /**
      2  6.设计一个类Circle,用来表示二维平面中的圆
      3  1> 属性
      4  * double radius (半径)
      5  * Point2D *point (圆心)
      6  
      7  2> 方法
      8  * 属性相应的set和get方法
      9  * 设计一个对象方法判断跟其他圆是否相交(重叠返回YES,否则返回NO)
     10  * 设计一个类方法判断两个圆是否相交(重叠返回YES,否则返回NO)
     11  */
     12 #import <Foundation/Foundation.h>
     13 #import <math.h>
     14 
     15 //
     16 @interface Point2D : NSObject
     17 {
     18     double _x; // x值
     19     double _y; // y值
     20 }
     21 // x值的getter和setter
     22 - (void)setX:(double)x;
     23 - (double)x;
     24 
     25 // y值的getter和setter
     26 - (void)setY:(double)y;
     27 - (double)y;
     28 
     29 // 同时设置x和y
     30 - (void)setX:(double)x andY:(double)y;
     31 
     32 // 计算跟其他点的距离
     33 - (double)distanceWithOther:(Point2D *)other;
     34 
     35 // 计算两个点之间的距离
     36 + (double)distanceBetweenPoint1:(Point2D *)p1 andPoint2:(Point2D *)p2;
     37 @end
     38 
     39 @implementation Point2D
     40 // x值的getter和setter
     41 - (void)setX:(double)x
     42 {
     43     _x = x;
     44 }
     45 - (double)x
     46 {
     47     return _x;
     48 }
     49 
     50 // y值的getter和setter
     51 - (void)setY:(double)y
     52 {
     53     _y = y;
     54 }
     55 - (double)y
     56 {
     57     return _y;
     58 }
     59 
     60 // 同时设置x和y
     61 - (void)setX:(double)x andY:(double)y
     62 {
     63     // 第1种思路
     64     // _x = x;
     65     // _y = y;
     66     
     67     // 第2种思路
     68     [self setX:x];
     69     [self setY:y];
     70 }
     71 
     72 // 计算跟其他点的距离
     73 - (double)distanceWithOther:(Point2D *)other
     74 {
     75     // 不要再傻乎乎算一遍了,直接调用类方法即可
     76     return [Point2D distanceBetweenPoint1:self andPoint2:other];
     77 }
     78 
     79 // 计算两个点之间的距离
     80 + (double)distanceBetweenPoint1:(Point2D *)p1 andPoint2:(Point2D *)p2
     81 {
     82     // 两点距离公式:( (x1-x2)的平方 + (y1-y2)的平方 )开根
     83     
     84     // x1-x2
     85     double xDelta = [p1 x] - [p2 x];
     86     // (x1-x2)的平方
     87     double xDeltaPingFang = pow(xDelta, 2);
     88     
     89     // y1-y2
     90     double yDelta = [p1 y] - [p2 y];
     91     // (y1-y2)的平方
     92     double yDeltaPingFang = pow(yDelta, 2);
     93     
     94     return sqrt(xDeltaPingFang + yDeltaPingFang);
     95 }
     96 @end
     97 
     98 //
     99 @interface Circle : NSObject
    100 {
    101     double _radius; // 半径
    102     Point2D *_point; // 圆心
    103 }
    104 
    105 // 半径的getter和setter
    106 - (void)setRadius:(double)radius;
    107 - (double)radius;
    108 
    109 // 圆心的getter和setter
    110 - (void)setPoint:(Point2D *)point;
    111 - (Point2D *)point;
    112 
    113 
    114 // 跟其他圆是否重叠(重叠返回YES,否则返回NO)
    115 - (BOOL)isInteractWithOther:(Circle *)other;
    116 // 判断两个圆是否重叠(重叠返回YES,否则返回NO)
    117 + (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2;
    118 
    119 @end
    120 
    121 @implementation Circle
    122 // 半径的getter和setter
    123 - (void)setRadius:(double)radius
    124 {
    125     _radius = radius;
    126 }
    127 - (double)radius
    128 {
    129     return _radius;
    130 }
    131 
    132 // 圆心的getter和setter
    133 - (void)setPoint:(Point2D *)point
    134 {
    135     _point = point;
    136 }
    137 - (Point2D *)point
    138 {
    139     return _point;
    140 }
    141 
    142 // 跟其他圆是否重叠(重叠返回YES,否则返回NO)
    143 - (BOOL)isInteractWithOther:(Circle *)other
    144 {
    145     return [Circle isInteractBetweenCircle1:self andCircle2:other];
    146 }
    147 
    148 // 判断两个圆是否重叠(重叠返回YES,否则返回NO)
    149 + (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2
    150 {
    151     // 如果两个圆心的距离 >= 两个圆的半径和,就不重叠
    152     // 如果两个圆心的距离 < 两个圆的半径和,就重叠
    153     
    154     // 两个圆心
    155     Point2D *point1 = [circle1 point];
    156     Point2D *point2 = [circle2 point];
    157     // 两个圆心的距离
    158     double distance = [point1 distanceWithOther:point2];
    159     
    160     // 半径和
    161     double radiusSum = [circle1 radius] + [circle2 radius];
    162     
    163     return distance < radiusSum;
    164 }
    165 @end
    166 
    167 int main()
    168 {
    169     Circle *c1 = [Circle new];
    170     // 设置半径
    171     [c1 setRadius:2];
    172     // 设置圆心
    173     Point2D *p1 = [Point2D new];
    174     [p1 setX:10 andY:10];
    175     [c1 setPoint:p1];
    176     
    177     Circle *c2 = [Circle new];
    178     // 设置半径
    179     [c2 setRadius:2];
    180     // 设置圆心
    181     Point2D *p2 = [Point2D new];
    182     [p2 setX:13 andY:14];
    183     [c2 setPoint:p2];
    184     
    185     // 圆心距离是5  半径和是4  所以不重叠
    186     BOOL b1 = [c1 isInteractWithOther:c2];
    187     
    188     BOOL b2 = [Circle isInteractBetweenCircle1:c1 andCircle2:c2];
    189     
    190     NSLog(@"%d %d", b1, b2);
    191     
    192     return 0;
    193 }

     

  • 相关阅读:
    logback 常用配置详解(二) <appender>
    logback 配置详解(一)
    logstash报错如下:Validation Failed: 1: this action would add [2] total shards, but this cluster currently has [999]/[1000] maximum shards open
    从字节码角度分析Byte类型变量b++和++b
    接口和抽象类有什么区别?你选择使用接口和抽象类的依据是什么?
    计算1至n中数字X出现的次数
    转:轻松搞定面试中的红黑树问题
    转:40个Java集合面试问题和答案
    自定义Adapter为什么会重复多轮调用getView?——原来是ListView.onMeasure在作祟
    何时调用getView?——从源码的角度给出解答
  • 原文地址:https://www.cnblogs.com/zhangxiaomeng1991/p/4159558.html
Copyright © 2011-2022 走看看