OC基礎--繼承

繼承的基本概念:ide

  現實生活中的繼承:工具

   人類是一個基類(也稱作父類),一般狀況下全部人類所共同具有的特性,若有手有腳能吃能喝性能

   按照生活常規,咱們繼續給人類來細分的時候,咱們能夠分爲學生類 工人類等,學生類和工人類一樣具有手 腳 吃 喝等特性,而這些特性是全部人類所共有的,那麼就可讓學生或工人類繼承人類,這樣當創建學生類和工人類的時候咱們無需再定義人類中已經有的成員和方法,而只須要描述學生類和工人類所特有的特性便可。學習

   學生類和工人類的特性是由在人類原有特性基礎上增長而來的,那麼學生類和工人類就是人類的派生類(也稱作子類)。以此類推,層層遞增, 這種子類得到父類特性的概念就是繼承spa

OC中的繼承關係code

  • B類繼承A類,那麼B類將擁有A類的全部屬性和方法,此時咱們說A類是B類的父類,B類是A類的子類
  • C類繼承B類,那麼C類將擁有B類中的全部屬性和方法,包括B類從A類中繼承過來的屬性和方法,此時咱們說B類是C類的父類,C類是B類的子類
  • 注意:
    • 基類的私有屬性能被繼承,不能在子類中訪問。
    • OC中的繼承是單繼承:也就是說一個類只能一個父類,不能繼承多個父類
    • 子類與父類的關係也稱爲isA(是一個)關係,咱們說 子類isA父類,也就是子類是一個父類,好比狗類繼承動物類,那麼咱們說狗isA動物,也就是狗是一個動物。再如汽車繼承交通工具,那麼們說汽車isA交工工具,也就是汽車是一個交通工具
    • 繼承的合理性:引用《大話西遊》裏的一句話來描述繼承的合理性。「人是人他媽生的,妖是妖他媽生的!」 以此類推 人妖是….

繼承是代碼重用的重要方式之一對象

  • 來感覺一下,  咱們定義個學生類和一個工人類  若是不使用繼承,  代碼以下:

    學生類聲明文件.h:blog

      #import <Foundation/Foundation.h> 

      @interface Student : NSObject
      {
          // 姓名
          NSString * _name;
          // 年齡
          int _age;
          // 學號
          int _studengNO;
          // 身份
          NSString * _identity;
      }
      - (void) setName:(NSString *) name;
      - (NSString *) name;
      - (void) setAge: (int) age;
      - (int) age;
      - (void) setStudentNO: (int) studentNO;
      - (int) studentNO;
      - (void) setIdentity: (NSString *) identity;
      - (NSString *) identity;
      //
      - (void) eat;
      // 學習
      - (void) study;
      @end

    學生類實現文件.m:繼承

            #import "Student.h" 

            @implementation Student
            - (void)setName:(NSString *)name{
                _name = name;
            }
            - (NSString *)name{
                return _name;
            }
            - (void)setAge:(int)age{
                _age = age;
            }
            - (int)age{
                return _age;
            }
            - (void)setStudentNO:(int)studentNO{
                _studengNO = studentNO;
            }
      - (int)studentNO{
          return _studengNO;
      }
      - (void)setIdentity:(NSString *)identity{
          _identity = identity;
      }
      - (NSString *) identity{
          return _identity;
      }
      //
      - (void)eat{
          NSLog(@"吃東西");
      }
      // 學習
      - (void)study{
          NSLog(@"學習");
      }
      @end           

    工人類聲明文件.h:接口

      #import <Foundation/Foundation.h> 

      @interface Worker : NSObject
      {
          // 姓名
          NSString * _name;
          // 年齡
          int _age;
          // 工號
          int _workNO;
          // 身份
          NSString * _identity;
      }
      - (void) setName: (NSString *) name;
      - (NSString *) name;
      - (void) setAge: (int) age;
      - (int) age;
      - (void) setWorkNO: (int) workNO;
      - (int) workNO;
      - (void) setIdentity: (NSString *) identity;
      - (NSString *) identity;
      //
      - (void) eat;
      // 學習
      - (void) study;
      // 工做
      - (void) work;
      @end

    工人類實現文件:

      #import "Worker.h"

       @implementation Worker
      - (void)setName:(NSString *)name{
          _name = name;
      }
      - (NSString *)name{
          return _name;
      }
      - (void)setAge:(int)age{
          _age = age;
      }
      - (int)age{
          return _age;
      }
      - (void)setWorkNO:(int)workNO{
          _workNO = workNO;
      }
      - (int)workNO{
          return _workNO;
      }
      - (void)setIdentity:(NSString *)identity{
          _identity = identity;
      }
      - (NSString *) identity{
          return _identity;
      }
      //
      - (void)eat{
          NSLog(@"吃東西");
      }
      // 學習
      - (void)study{
          NSLog(@"學習");
      }
      // 工做
      - (void)work{
          NSLog(@"上班了 幹活");
      }
      @end

  比較一下上面的代碼   看看有多少是重複的:

    聲明文件中重複部分:

      屬性:

          // 姓名
          NSString * _name;
          // 年齡
          int _age;
          // 身份
          NSString * _identity;

      行爲:

        - (void) setName:(NSString *) name;
        - (NSString *) name;
        - (void) setAge: (int) age;
        - (int) age;
        - (void) setIdentity: (NSString *) identity;
        - (NSString *) identity;
        //
        - (void) eat;
        // 學習
        - (void) study; 

    實現文件中重複部分:

        - (void)setName:(NSString *)name{
            _name = name;
        }
        - (NSString *)name{
            return _name;
        }
        - (void)setAge:(int)age{
            _age = age;
        }
        - (int)age{
            return _age;
        }
        - (void)setIdentity:(NSString *)identity{
            _identity = identity;
        }
        - (NSString *) identity{
            return _identity;
        }
        //
        - (void)eat{
            NSLog(@"吃東西");
        }
        // 學習
        - (void)study{
            NSLog(@"學習");
        } 

  獲得的結果是:

    學生類中就一個學號在工人類中沒有

    工人類中就一個工號和一個工做的行爲在學生類中沒有

    其他部分都是重複代碼

    若是還要添加幾個其餘類:  如學前期的幼兒類    退休後的老人類等等   那麼上面那些重複的代碼還得重複好幾遍   複製粘貼都感受累有木有

 

如今咱們來添加一個Person類   人類中定義屬性有 姓名 (name) 年齡(age)  身份(identity)  行爲有 吃(eat) 學習(study)

使用繼承關係後再來看看代碼:

  Person類聲明文件:

    #import <Foundation/Foundation.h>

    @interface Person : NSObject
    {
        // 姓名
        NSString * _name;
        // 年齡
        int _age;
        // 身份
        NSString * _identity;
    }
    - (void) setName:(NSString *) name;
    - (NSString *) name;
    - (void) setAge: (int) age;
    - (int) age;
    - (void) setIdentity: (NSString *) identity;
    - (NSString *) identity;
    //
    - (void) eat;
    // 學習
    - (void) study; 
    @end

  Person類實現文件:

    #import "Person.h"

    @implementation Person
    - (void)setName:(NSString *)name{
        _name = name;
    }
    - (NSString *)name{
        return _name;
    }
    - (void)setAge:(int)age{
        _age = age;
    }
    - (int)age{
        return _age;
    }
    - (void)setIdentity:(NSString *)identity{
        _identity = identity;
    }
    - (NSString *) identity{
        return _identity;
    }
    //
    - (void)eat{
        NSLog(@"吃東西");
    }
    // 學習
    - (void)study{
        NSLog(@"學習");
    }
    @end

  學生類聲明文件:

    #import <Foundation/Foundation.h>
    #import "Person.h" 

    @interface Student : Person
    {
        // 學號
        int _studengNO;
    }
    - (void) setStudentNO: (int) studentNO;
    - (int) studentNO;
    @end

  學生類實現文件:

    #import "Student.h"

    @implementation Student 
    - (void)setStudentNO:(int)studentNO{
        _studengNO = studentNO;
    }
    - (int)studentNO{
        return _studengNO;
    }
    @end

  工人類的聲明文件:

    #import <Foundation/Foundation.h>
    #import "Person.h" 
  
    @interface Worker : Person
    {
        // 工號
        int _workNO;
    }
    - (void) setWorkNO: (int) workNO;
    - (int) workNO;
    // 工做
    - (void) work;
    @end

  工人類的實現文件:

    #import "Worker.h"

    @implementation Worker 
    - (void)setWorkNO:(int)workNO{
        _workNO = workNO;
    }
    - (int)workNO{
        return _workNO;
    }
    // 工做
    - (void)work{
        NSLog(@"上班了 幹活");
    }
    @end 

  好了, 如今再來看看代碼: 咱們的代碼中多了一個Person類的聲明和實現文件   在這個類中聲明定義的就是咱們以前學生類和工人類中重複的那一部分.

  "B類繼承A類,那麼B類將擁有A類的全部屬性和方法" 就是說若是 咱們讓學生類和工人類都繼承自Person類  , 那麼就算咱們在學生類中和工做類中都沒有聲明那些姓名 年齡 吃 學習之類的屬性和方法,  這兩個類也能從Person類中獲得這些行爲屬性.  而在學生類中只須要聲明學生類特有的學號屬性, 工人類中只須要聲明工人類特有的工號,工做這種特有的行爲屬性便可,  這樣子在學生類和工人類中得代碼看起來簡潔了不少, 並且之後若是咱們須要再添加什麼嬰兒類  老人類, 也只須要在相關類中添加他們特有的行爲屬性就好了.

  在這個例子裏, Person類就是父類   學生類和工人類就是Person類的子類,  須要注意的是OC也是單繼承的,  畢竟咱都只有一個父親是吧, (呃   那個   乾爹不算) ,  在父類中定義的全部行爲屬性,  子類都能繼承過去,  而在子類中還能夠添加他特有的行爲屬性,   也就是說我爸有的 我都有,  我有的, 我爸不必定有(例如: 我會打Dota  我爸不會 ).

  當咱們發現兩個類中有定義不少重複的行爲屬性的時候, 即可以把這些重複的部分都抽取出來當一個父類;  繼承對代碼的重用性和可擴展性 , 看上面例子體會一下吧

OC中繼承的實現格式:

  @interface 子類名稱 : 父類名稱

  @end

    記得導入父類頭文件

 繼承:

     當B類繼承A類, 那麼B類就擁有A類全部的屬性和方法(類方法/對象方法)     

     優勢:

           提升代碼的複用性

           可讓類與類之間產生關係, 正是由於繼承讓類與類之間產生了關係因此纔有了多態     

  缺點:   增長了代碼之間的耦合性

     注意: 

           不要覺得繼承能夠提升代碼的複用性, 之後但凡發現多個類當中有重複代碼就抽取一個父類

           只要知足必定的條件咱們才能使用繼承

                條件: XXXX 是 XXX   /    某某某 is a 某某某    (繼承是  '是' 的關係   接口(協議) 是 '有' 的關係)

方法的重寫:

  • 在子類中實現與父類中同名的方法,稱之爲方法重寫( 方法名相同   方法體不一樣   子類提供新的實現)
  • 重寫之後當給子類發送這個消息的時候,執行的是在子類中重寫的那個方法,而不是父類中的方法
  • 若是想在子類中調用被子類重寫的父類的方法,能夠經過super關鍵字
  • 使用場景:當從父類繼承的某個方法不適合子類,能夠在子類中重寫父類的這個方法

  方法重寫: 子類從父類繼承了父類的方法(行爲)  可是不想用父類的實現體   能夠本身提供新的實現覆蓋掉父類的實現

    舉例:  我爸會打人   我從我爸那也繼承了打人的行爲  我爸打人用拳頭打    可是我感受用拳頭打不爽   就能夠用本身的方式去打 (如用板磚砸)      這樣雖然都是打人的方法   可是我用板磚打覆蓋了從我爸那繼承來的用拳頭打     這樣方法名相同   可是方法的實現子類和父類不一樣(子類的實現覆蓋了父類的實現)   就是方法的重寫

  在上面例子中咱們來重寫父類學習的方法:

    Person類中得學習方法實現:

    // 學習
    - (void)study{
        NSLog(@"學習");
    }

    工人類重寫父類的學習方法:

    // 學習
    - (void)study{
        NSLog(@"咱們在職人員經過上網來學習");
    }

    學生類重寫父類的方法:

    // 學習
    - (void)study{
        [super study];
        NSLog(@"咱們學生都經過去上課來學習");
    } 

繼承中方法調用的順序:

  一、在本身類中找

  二、若是沒有,去父類中找

  三、若是父類中沒有,就去父類的父類中

  四、若是父類的父類也沒有,就還往上找,直到找到基類(NSObject)

  五、若是NSObject都沒有就報錯了

  以上若是找到了就執行這個方法,就再也不日後查找了

 繼承的注意事項:

  • 子類不能定義和父類同名的成員變量,私有成員變量也不能夠;由於子類繼承父類,子類將會擁有父類的全部成員變量,若在子類中定義父類同名成員變量 屬於重複定義。
  • OC類支持單一繼承,不支持多繼承;也就是說一個類只能有一個直接父類
  • OC類支持多層繼承

super關鍵字:

  概念: super是個編譯器的指令符號,只是告訴編譯器在執行的時候,去調誰的方法

  做用:    直接調用父類中的某個方法

         super在對象方法中,那麼就會調用父類的對象方法     super在類方法中,那麼就會調用父類的類方法

  使用場合:   子類重寫父類的方法時想保留父類的一些行爲

相關文章
相關標籤/搜索