• 黑马程序员——OC语言基本语法知识(一)


     
     
    *** 封装 ***
    一、 set方法

    通过 指针->成员变量名 方式给成员变量赋值具有危险性, 可能被赋值为不合理的数值。不允许通过指针直接修改成员变量, 就要去掉@public。 通过方法来修改成员变量的值, 方法中可以加代码保证接收的值是合理的赋值。

    设置成员变量属性值的方法, 通常称为该属性的set方法, 命名方式为 setAge: , 接收一个相同类型的参数,形参的名称不能和成员变量名相同。

     举例:

     
    1. - (void)setAge:(int)newAge   
    2. {  
    3.         // 对传进来的参数值进行过滤, 保证数据安全性  
    4.         if (newAge <= 0)  
    5.                 newAge = 1;  
    6.   
    7.         // 把参数值赋给成员变量  
    8.         age = newAge;  
    9. }  
    10.    


    在 main函数中调用set方法:

    [stu setAge:18];    // 赋值为18

    [stu setAge:-18];   // 默认赋值为1

    以后就不要写@public了, 必须要通过set方法来设置成员变量。 可以保证成员变量数据的合理性。

     

    二、 get方法

     

    没有@public, 我们就不能通过 stu->age 来查看成员变量的值 (被保护)。我们要通过调用方法来返回成员变量值。

     

    get方法: 返回该对象的成员变量值。

     举例

     
    1. - (int) age   
    2. {  
    3.         return age;  
    4. }  
    5.    


    在main函数中调用get方法获得age属性的值:

    int myAge = [stu age];

    注意: 不是所有的成员变量都有set和get方法, 如果有的成员变量是只读属性(read only), 只能被访问, 不能被修改, 这样的情况就可以只提供get方法, 不写set方法。

     

    三、 封装的好处

    封装可以保证数据的安全性。 如果要给成员变量赋值, 必须通过set方法进行访问, 在set方法中, 可以添加对不合理的属性值的过滤。

     

    四、 命名规范

    在get方法中, 方法名和返回的成员变量名是一样的, 可读性不好。 所以规范成员变量名以下划线开头, 便于和get方法名和局部变量名区分。

    成员变量名规范以 

    1. @interface Student : NSObject  
    2. {  
    3.         int _age;      // 规范的的成员变量名  
    4. }  
    5. @end  
    6.    
    7. - (void) setAge:(int)age   
    8. {  
    9.         _age = age;    // 这样set方法的形参名就可以和成员变量同名了(没有下划线)  
    10. }  
    11. - (int) age    
    12. {  
    13.         return _age;  
    14. }  
    15.    
    16. // 调用是相同的  
    17. [stu setAge:18];  
    18. int myAge = [stu age];  


    *** 继承 ***

     

    一、 基本概念

    类B继承了类A, 那么类B具有类A的所有属性和方法。

    在OC中继承关系用 : 表示。

    比如我们要写一个Dog类和一个Cat类, 两个类拥有相似的成员变量和方法, 不想把代码复制很多遍。可以写一个Animal类, 把猫和狗相同的内容放到Animal里, 然后让Dog和Cat继承Animal类。

    二、 优缺点

    继承的好处: 子类拥有父类的所有成员变量和方法, 减少重复代码. 建立类之间的关系。

    继承的缺点: 代码耦合性太强 (类之间的关系太紧密, 如果某个类坏了, 另一个类会受影响)。

    我们的类如果不继承NSObject就没有new方法, 就没有创建对象的能力。我们的类能够调用new方法, 说明NSObject类拥有new方法。可以查看NSObject类的说明, 找到 +new 方法。

    NSObject是基类, 几乎所有的类最终都是继承于它。也有的类不是继承NSObject的, 比如NSProxy, 它也是一个基类。

    子类有自己的成员变量方法和父类的所有成员变量和方法 (以及父类的父类的)。

    *** 多态 ***

    有继承才有多态。

    多态就是可以用父类的指针指向子类的对象. 不管用什么指针, 调用方法时调用的都是对象的方法。

     

    一、 多态的好处:

    可以使用父类指针来代表各种子类对象调用函数,节省代码。

    比如, 我们有一个Cat类, 有eat方法; 还有一个Dog类, 也有eat方法

     
    1. @interface Cat : Animal  
    2. - (void) eat;  
    3. @end  
    4.    
    5. @implementation Cat  
    6. - (void) eat   
    7. {  
    8.         NSLog(@"Cat is eating");  
    9. }  
    10. @end  


      

    我们想写函数来喂动物, 喂Dog和Cat由于参数类型不同, 需要对每种类型都写一个函数:


     
    1. void feed(Dog *d)   
    2. {  
    3.         [d eat];  
    4. }  
    5. void feed2(Cat *c )    // 不允许同名函数  
    6. {  
    7.         [c eat];  
    8. }  
    9. int main()   
    10. {  
    11.         Dog *d = [Dog new];  
    12.         feed (d);      // 喂狗  
    13.         Cat *c = [Cat new];  
    14.         feed2 (c);    // 喂猫  
    15.         return 0;  
    16. }  


    这两个函数体是很相似的, 而且如果有更多的动物, 还要写很多相似的函数, 很麻烦, 还要使用不同的名字。

    这样,就可以使用多态来简化,写一个Animal类, 作为Dog 和Cat的父类, 这样在函数中就可以使用Animal *指针, 来指代Dog或Cat类型的参数:

     


     
    1. void feed(Animal *a)     // a既可以是Dog, 也可以是Cat, 也可以是其它Animal  
    2. {  
    3.         [a eat];         // 调用对象的eat方法  
    4. }  
    5. int main()   
    6. {  
    7.         Dog *d = [Dog new];  
    8.         feed (d);        // 调用的是Dog的eat方法  
    9.         Cat *c = [Cat new];  
    10.         feed (c);        // 调用的是Cat的eat方法  
    11.         Animal *a = [Animal new];  
    12.         feed (a);  
    13. }  


    这样只需要写一个函数, 很方便, 而且调用的还都是每个对象自身的方法。

    二、 多态的局限性

    不建议用父类指针调用子类的特有方法。

    如果用父类指针调用子类在父类中没有的方法, 虽然调用的是子类对象的方法, 但是编译器会报警告, 因为它只能看到用父类的指针调用一个父类没有的方法。

    举例

    1. @implementation Animal  
    2. @end  
    3. @implementation Dog  
    4. - (void) run { ... }  
    5. @end  
    6. int main()   
    7. {  
    8.         Animal *a = [Dog new];  
    9.         [a run];  
    10.         return 0;  
    11. }  
    12. 可以正确运行, 但是编译器会警告。  
    13. 如果必须要这么写, 规范方法是进行强制类型转换:  
    14. int main()   
    15. {  
    16.         Animal *a = [Dog new];  
    17.         Dog *d = (Dog *)a;  
    18.         [d run];  
    19.         return 0;  
    20. }  
  • 相关阅读:
    Linux切换到su超级用户
    使用Qt ARM交叉编译提示“此qt版本具有一个未知的工具链”
    使用qwt提示error LNK2001 问题的解决方法
    JavaScript中的 in
    JavaScript中的this
    autocad2010指令全集
    Proj.NETProj.NET简介和示例(转载)
    高性能地图优化策略(转载)
    Emgu.CV,OpenCV for C#
    C# 转载网络爬虫
  • 原文地址:https://www.cnblogs.com/HtercelH/p/4033735.html
Copyright © 2020-2023  润新知