黑马程序员技术交流社区

标题: 构造方法_总结 [打印本页]

作者: huh    时间: 2015-12-17 10:59
标题: 构造方法_总结
是什么?
    对象初始化时,运行的方法!
有两个方法:
        +alloc : (类方法)给对象分配空间的方法        -init:(对象方法)初始化对象的方法,<真正的构造方法>
有什么用?
    在对象初始化的适合,就给属性赋值!
    (如:当需要创建此类很多对象时,可以避免多行代码
       Person *per1 = [Person new];
       per1.age =10;
       per1.name =@"huh";
       ...
   //构造方法只要一行代码 
   Person *per1 = [[Person alloc]init]
    )
    场景1:在对象创建的一瞬间,就给对象赋值!
    场景2:   在创建对象的时候,我想要动态的给对象赋值!
    场景3:   让子类能够给自己的属性,初始化的时候能够赋值!
怎么用?
    重写构造方法-(id) init
    自定义构造方法-(id)initXXX
    自定义子类的构造方法 -(id)initXXXX
    Person *per3 = [[Person alloc] init];
用的时候注意什么?
    1.NSObject的init方法必须调用
    2.在没有特殊要求的情况下,子类和父类的赋值都应该在各自的类里面,各司其职,
       这样才能隔离父类的变化!
  1. //  Person.h
  2. #import <Foundation/Foundation.h>
  3. @interface Person : NSObject
  4. //子类重写父类,声明不声明都可以
  5. //-(id)init;
  6. @property int age;
  7. @end
  8. //
  9. //  Person.m
  10. //
  11. #import "Person.h"
  12. @implementation Person
  13. /*
  14. 场景1:在对象创建的一瞬间,就给对象赋值!(对象创建的时候,必须调用init方法)
  15. 子类重写父类的init方法,(init是真正的构造方法),
  16. 在init方法里面,给属性赋值,就能实现初始化时,就给属性赋值的需求!
  17. -(id)init{
  18. _age = 10; //这还不够!
  19. }
  20. 父类的init方法里面有很多的操作,我不知道!(如:我并不知道父类的init,是如何进行实力化得)
  21. 因为子类重写父类的方法后,就不会在执行父类里面的操作,只会执行子类的方法了!
  22. 可我想要的是,执行父类里面的操作 -- 创建对象!创建对象的同时,给属性赋值?
  23. 【super init】 调用父类的init方法,self = 【super init】 用本身对象去接收!

  24. 严谨:
  25.     如果初始化失败,该怎么办?初始化失败会返回nil,就不需要对属性赋值! nil ==0;
  26.     if (self != nil) {}

  27. 注意:重写父类的方法,不需要声明也可以!
  28. */
  29. -(id)init{
  30.     if (self = [super init]) {//原理,非0则为真!
  31.          _age =13;
  32.     }
  33.    
  34.     return self;
  35. }
  36. @end
  37. //
  38. //  Cat.h
  39. //
  40. #import <Foundation/Foundation.h>
  41. @interface Cat : NSObject
  42. @property NSString *name;
  43. @property int age;
  44. -(id)initCat:(NSString*) name Age:(int)age;
  45. @end
  46. //
  47. //  Cat.m
  48. //
  49. /*
  50. 场景2:在创建对象的时候,我想要动态的给对象赋值!
  51.     直接对重写父类的-(id)init方法,进行传参 ----不对,因为父类并没有带参数init方法!
  52.     自定义带参数的init方法里面调用父类的init方法!

  53. 注意:方法一定要声明,因为调用的是自己的方法,而不是父类的方法!
  54. */
  55. #import "Cat.h"
  56. @implementation Cat
  57. -(id)initCat:(NSString*) name Age:(int)age{
  58.     if(self = [super init]){
  59.         _age = age;
  60.         _name = name;
  61.     }
  62.    
  63.     return self;
  64. }
  65. @end
  66. //
  67. //  BSCat.h
  68. //
  69. #import <Foundation/Foundation.h>
  70. #import "Cat.h"
  71. @interface BSCat : Cat
  72. @property NSString *color;//颜色
  73. -(id)initBSCat:(NSString *)name Age:(int)age Color:(NSString *)color;
  74. @end
  75. //
  76. //  BSCat.m
  77. //
  78. #import "BSCat.h"
  79. @implementation BSCat
  80. /*
  81. 场景3:让子类能够给自己的属性,初始化的时候就赋值!且继承父类的属性也能够动态赋值?
  82. 分析:   首先它是个自定义的动态初始化
  83.         -(id)initBSCat:(NSString *)name Age:(int)age Color:(NSString *)color
  84.         可是,因为父类给属性,定义的是@property
  85.         (@property自动生成的属性的默认是@private权限,只能在本类使用,不能在子类使用)
  86.         所以,两种解决方案
  87.           1) 手动更改父类的get和set方法!(缺陷,可扩展性差.如:父类要改个名字,子类也要跟着改)
  88.              调用NSObject 的init方法
  89.              if(self=[super init]){
  90.              _name = name;//_name2 = name;
  91.              _age =age;
  92.              _color = color;
  93.              }
  94.           2) 调用父类Cat的initCat方法!(父类的修改,对子类没有影响.)

  95. */
  96. -(id)initBSCat:(NSString *)name Age:(int)age Color:(NSString *)color{
  97.    
  98.     if(self =[super initCat:name Age:age]){//调用父类的方法
  99.         _color = color;//添加自己的操作
  100.         
  101.     }
  102.     return self;
  103. }
  104. @end
  105. /*
  106.     main.m
  107.     构造方法
  108.     是一个对象在初始化的时候执行的方法.
  109.     init才是真的构造方法
  110.     构造方法的操作有两种:
  111.     1.重写.
  112.     优点:实现简单. 不足:不能够根据不同对象赋不同的值,属性的值是固定的.
  113.     2.自定义构造
  114.     优点:使用灵活,可以根据不同的对象给属性设定不同的值. 不足:写法比较麻烦一些.
  115.     3.子类继承父类自定义构造的写法.
  116.     在子类里自定义构造时,要调用父类的自定义构造,而不是NSObject的init.这样才能隔离父类的变化.
  117.     而且,父类的属性可以保持私有化private.
  118. */
  119. #import <Foundation/Foundation.h>
  120. #import "Person.h"
  121. #import "Cat.h"
  122. #import "BSCat.h"
  123. int main(int argc, const char * argv[]) {
  124.     /*
  125.      new 方法其实是封装了两个方法
  126.      +alloc:给对象分配一块内存(类方法)
  127.      -init:初始化这个对象(对象方法)
  128.      */
  129. //    Person *per = [Person new];
  130.    
  131. //    可以不初始化对象,直接赋值,但是不推荐,有时会出不可预知的错误
  132. //    Person *per1 = [Person alloc];
  133. //    per1.age =10;
  134. //    NSLog(@"age1 =%d",per1.age);
  135.    
  136. //    标准方式
  137. //    Person *per3 = [[Person alloc] init];
  138. //    Person *per1 = [Person alloc];
  139. //    Person *per2 = [per1 init];
  140. //    per2.age =20;
  141. //    NSLog(@"age2 =%d",per2.age);
  142. //    简洁方式
  143.     Person *per3 = [[Person alloc] init];
  144.     per3.age =30;
  145.     NSLog(@"age3 =%d",per3.age);
  146. //    场景1:在对象创建的一瞬间,就给对象赋值!(对象创建的时候,必须调用init方法)
  147.     Person *per4 = [[Person alloc]init];
  148.     NSLog(@"age4 = %d",per4.age);
  149.    
  150.    
  151. //    场景2:   在创建对象的时候,我想要动态的给对象赋值!
  152.     Cat *ct = [[Cat alloc]initCat:@"boshimao" Age:3];
  153.     NSLog(@"name = %@ ,age = %d",ct.name,ct.age);
  154.    
  155.    
  156. //    场景3:让子类能够给自己的属性,初始化的时候就赋值!且继承父类的属性也能够动态赋值?
  157. //    以下两个输出的结果是一样得,因为在BSCat实现里面,调用的就是父类的init方法!
  158. //    Cat *ca =[[BSCat alloc] initBSCat:@"boSiMao" Age:2 Color:@"hua"];
  159. //    NSLog(@"name=%@ ,age =%d, color%@",ca.name,ca.age,((BSCat *)ca).color);
  160.    
  161.     BSCat *bs =[[BSCat alloc] initBSCat:@"boSiMao" Age:2 Color:@"hua"];
  162.     NSLog(@"name = %@ ,age =%d, color = %@",bs.name,bs.age,bs.color);
  163.         return 0;
  164. }
复制代码




作者: 学习黑马精神    时间: 2015-12-17 17:50
学习了!
作者: 长厢厮守℡    时间: 2015-12-17 23:40
总结的很不错




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2