• 黑马程序员_ Objective-c 面向对象笔记详解


    1)类,对象,方法

    类名:

    1) 类名的第一个字母必须是大写

    2) 不能有下划线

    3) 多个英文单词,用驼峰标识

    类的声明和实现

    类的声明

    @interface 类名 : NSObject

    {

                      @public

                      成员变量;

    }

    方法声明;

    @end

    类的实现

    @implementation 类名

    方法实现;

    @end

    举例说明:

    1. //Horse类的声明  
    2. @interface Horse : NSObject  
    3. {  
    4.     @public //使成员变量可以让外部访问  
    5.       
    6.     //定义成员变量color,weight  
    7.     charchar *color;  
    8.     int weight;  
    9. }  
    10. //方法声明(方法前必须加减号’-’且数据类型必须加括号())  
    11. - (void)eat;  
    12. @end  
    13.   
    14. //类的实现  
    15. @implementation Horse  
    16.   
    17. - (void)eat  
    18. {  
    19.     NSLog(@"%s色,体重为%d的马吃草,",color,weight);  
    20. }  

    常见错误:OC语言编译时与C语言相同,一样是从上到下顺序编译,所以如果 类的声明和实现写在后面会报错,可以将类声明单独提到调用前的位置,也可将类声明和实现都提上去

    对象

    对象的创建

    1. //创建一个Horse类的对象s  
    2. Horse *s=[Horse new];  
    3.   
    4. //给对象s的属性的赋值,用符号:->  
    5. s->color="red";  
    6. s->weight=200;  
    7.   
    8. <pre name="code" class="objc">//使用对象s调用方法eat  
    9. [s eat];  
    
    
    

    1) 在OC中,要调用对象,就必须使用指针

    创建对象:类名 *p=[类名 new];

    1. //创建一个Horse类的对象s  
    2. Horse *s=[Horse new];  

    匿名对象:[[类名 new] 对象方法];红色部分即为匿名对象

    1. //创建并使用匿名对象调用eat方法  
    2. [[Horse new] eat];  

    OC语言中,对象分配内存后,系统并不自动回收,直到程序结束或手动回收

    2) 在OC中,要执行一些行为(方法),就必须写上一个中括号[行为执行者 行为名称]

    1. //使用对象s调用方法eat  
    2. [s eat];  

    方法

    方法即对象的行为

    1) 方法:方法名、参数、返回值(同样是声明和实现)

    2) 只要是OC对象的方法,必须以减号’-’开头

    3) OC方法中任何数据类型都必须用小括号()扩住

    方法的声明和实现

    1) 有返回值无参数的方法

    声明:

    [objc] view plaincopy
     
    1. - (int)eat;   //返回int类型  

    实现:

    [objc] view plaincopy
     
    1. - (int)eat  
    2. {  
    3.      方法体;  
    4. }  

    2) 带参数且有返回值的方法

    • 带一个参数

    声明:

    [objc] view plaincopy
     
    1. - (double) squre:(double)number;  

    实现:

    [objc] view plaincopy
     
    1. - (double) squre:(double)number  
    2. {  
    3.     方法体;  
    4. }  
    • 带多个参数

    声明:

    [objc] view plaincopy
     
    1. -(double)sumOfNum1:(double)number1 andNum2:(double)num2;  

    实现:

    [objc] view plaincopy
     
    1. -(double)sumOfNum1:(double)number1 andNum2:(double)num2  
    2. {  
    3.     方法体;  
    4. }  

    解读:

    1. - (double)sumOfNum1:(double)number1andNum2:(double)num2;  

    方法前减号’-’:表明方法类型,对象方法为减号’-'

    减号后double:表示返回数据类型

    (sumOfNum1:   andNum2:)括号里为方法名,注意包括冒号:

    冒号后double:表示参数类型

    number1:表示参数名

    方法调用

    [对象指针 方法名];

    如:[c sumOfNum1:10 andNum2:21];

    方法总结:

    OC方法中,一个参数对应一个冒号

    冒号:也是方法名的一部分

    方法中有多个参数时,要有多个冒号,且官方标准冒号前应该多写变量注释,即方法名尽量详细描述方法功能

    封装

    封装基本介绍

    set方法

    作用:提供一个方法给外界设置成员变量的值,可以在方法里面对参数进行相应过滤

    命名规范:

    1) 方法名必须以set开头

    2) set后面跟上成员变量的名称,成员变量首字母必须大写

    3) 返回值一定是void

    4) 一定会接受一个参数,且参数类型跟成员变量类型一致

    5) 形参名称不能跟成员变量一样

    get方法

    作用:返回对象内部的成员变量

    命名规范:

    1) 一定有返回值,返回值类型一定与成员变量类型一致

    2) 方法名跟成员变量类型一致(区别于其他语言以get开头,苹果官方不建议如此)

    3) 不会接受参数

    封装的好处

    实现成员变量的只读(即:可以只提供get方法)

    成员变量的命名规范

    命名规范:一定要以下划线_开头

    作用:

    1) 让成员变量和get方法的名称区分开

    2) 可以跟局部变量区分开,看到下划线开头的变量,一般即为成员变量

    弱语法

    OC在运行过程中才会检测对象是否实现相应的方法(区别于C语言在链接时检测)

    OC语言中,当类和对象方法的声明以及实现在main()函数前面时:

    1) 类声明可以缺失,仅报warning

    2) 方法声明也可以缺失,正常运行

    注:声明在main()前,实现在main()后市,缺失会直接报错

    类方法

    基本使用

    1) 类方法以加号’+’开头

    2) 直接用类名调用

    类方法与对象方法

    对象方法

    1) 减号’-’开头

    2) 只能由对象调用

    3) 对象方法中能访问当前对象的成员变量(实例变量)

    类方法

    1) 加号’+’开头

    2) 只能由类(名)来调用

    3) 类方法中不能访问成员变量(实例变量)

    类方法的好处和使用场合

    好处:

    1) 不依赖于对象,执行效率高

    2) 能用类方法,尽量用类方法

    使用场合:当方法内部不需要使用到成员变量 时,就可以改为类方法

    工具类

    工具类:基本没有成员变量,里面的方法基本都是类方法的类

    self(本质是一个指针)

    self概念:指向当前方法调用者(在对象方法中指向当前调用对象,在类方法中指向当前类)

    格式:

    [self 方法名];

    使用时注意死循环(方法内部不能用self调用本身)

    继承

    基本使用

    OC中继承用冒号’:’

    继承的好处

    1) 抽取重复代码

    2) 建立了类之间的关系

    3) 子类拥有父类中的所有成员成员变量和方法

    重写:

    子类重新实现父类中的某个方法,覆盖以前的做法

    使用注意:

    1) 父类必须声明在子类的前面

    2) 子类不能拥有和父类相同的成员变量

    3) 调用某个对象方法时,优先去当前对象中找,如果找不到,去父类中找

    继承和组合

    继承:A是B(类)

    组合:A拥有B(类)即:B类为A类的成员变量

    继承-super

    super的作用

    1) 直接调用父类中的某个方法

    2) Super在对象方法中,那么就会调用父类的对象方法;super在类方法中时,那么就会调用父类的类方法

    3) 使用场合:子类重写父类的方法时想保留父类的一些行为的时候

    多态(父类指针指向子类对象)

    基本使用

    动态绑定:调用方法时会检测指向的真实对象

    多态的好处

    当多个函数调用多个子类的相同对象方法时,可以利用多态将多个函数写为一个函数

    多态的局限性

    局限性:不能用父类类型的指针直接调用子类特用的方法(会报warning,可通过强制类型转换后使用)

    强制类型转换:

    [objc] view plaincopy
     
    1. Animal *a=[Dog new];  
    2. //强制将Animal类型的指针a转换为Dog类型的指针a并赋值给d  
    3. Dog *d=(Dog *)a;  

    多态总结

    1) 没有继承就没有多态

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

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

    4) 局限性(同上)

    开发技巧

    NSSting(NSString是一个字符串类)

    基本使用;字符串输出时,格式输出符为’%@’

    作业讲解

    1.使用类定义对象及参数的时候注意星号’*’。

    2.经验写法:方法返回值为 BOOL类型时,方法名一般都以is开头。

    3.当类成员变量为对象时,在为这个成员变量初始化赋值时,必须先创建对象并赋值,然后调用set方法将对象传递给该类的对象成员变量。

    多文件开发

    1. 定义一个类分2个文件:.h声明文件、.m实现文件

    .h:包含成员变量、方法的声明(即类声明)

    .m:包含方法的实现

    2. 如果要使用某一个类,只需要#import类的.h文件即可。

    Xcode功能演示

    1. Xcode断点调试功能

    即:可以在程序代码中任意行设置任意个断点调试程序,可实现代码逐行执行,并能查看执行结果。

    2. Xcode代码段保存功能

    即:可以将复用频率高的代码块保存起来以便以后直接调用。

    长按左键实现

    3. Xcode注释标记功能

    #pragma mark 注释语句(或作为书签标记用)

    对后面的一个方法进行注释

     #pragma mark –注释语句

    加‘-’ 后Xcode会将后面所有的方法进行注释,直到遇到下一个加‘-’ 的注释,这样即可实现代码的分类注释。

    4. Xcode多文件同时查看功能

    Xcode可以同时查看多个文件。

    如:同时查看.h和.m文件。

    核心语法

    点语法(编译器特性)

    1. 点语法基本使用

    本质:点语法本质是调用set和get方法。

    2. 点语法使用注意

    Person *p=[Person new];

    OC中点语法:

    p.age=10就等同于[p setAge:10]调用set方法

    Int a=p.age等同于[p age]调用get方法

    使用过程中set方法和get方法表示上都为p.age,具体调用哪个方法编译器会。通过判断是否赋值区别

    由于点语法为方法调用,使用过程中注意不要在方法内使用点语法调用本身方法,会造成死循环

    成员变量的作用域

    1. OC中,成员变量的作用域分以下四种:

    @public (公开的)在有对象的前提下,任何地方都可以直接访问。

    @protected (受保护的,默认情况下就是受保护的)只能在当前类和子类的对象方法中访问

    @private (私有的)只能在当前类的对象方法中才能直接访问

    @package (框架级别的)作用域介于私有和公开之间,只要处于同一个框架中就可以直接通过变量名访问

    2.  成员变量作用域使用注意

    OC中没有类声明,只有类实现,也可以定义一个类。(知道即可,一般没人这样写),且定义在类实现implementation中的成员变量默认为私有的,即时加上@public也不能在任何地方访问,因为其他文件只导入.h文件,在其他文件中这些成员变量是不可见的(除非类实现implementation写在了main()函数的前面,这时main()函数可以调用)。

    类实现implementation中定义成员变量时,不能重复定义声明中的成员变量。

    @property和@synthesize

     @property

    Xcode编译器中使用@property可以自动生成成员变量的set和get方法的声明。

    如:成员变量为:int _age;

    则@property int age ;语句就表示同时声明了setAge和getAge方法,等价于:

    [objc] view plaincopy
     
    1. - (void)setAge:(int)age;  
    2. - (int)age;  

    解读@property int age ;

    int位置为所要声明的成员变量的数据类型

    age位置为所要声明的set方法中传入的形参名称

    @synthesize

    Xcode编译器中使用@sythesize可以自动成员变量的set和get方法的实现。

    如:成员变量为:int age;

    则@synthesize age=_age;语句表示同时实现了set和get方法,等价于:

    1. - (void)setAge(int)age  
    2. {  
    3.            _age=age;  
    4. }  
    5.   
    6. - (int)age  
    7. {  
    8.            return  _age;  
    9. }  

     

    解读@synthesize  age = _age;

    =等号左边的age表示生成声明为age的方法

    =等号右边的_age表示访问_age成员变量

    @property和@synthesize的最简写法

    Xcode4.2以后版本呢,编译器支持一句@property同时完成-成员变量在声明中的定义-成员变量set和get方法的声明-成员变量set和get方法的实现。

    如:@interface Car:NSObject

           @property int speed;

           @end

           @implementation Car

           @end

    则以上代码可正常运行,编译器会自动生成-成员变量在声明中的定义(自动生成_speed变量,但自动生成的变量为私有的private)-成员变量set和get方法的声明-成员变量set和get方法的实现。

    使用细节

    @synthesize细节

    @synthesize speed=_speed;

    生成的实现方法访问_speed变量

    @synthesize speed;

    生成的实现方法默认访问speed变量,如果没有speed变量,编译器会自动生成speed变量,且生成的speed变量默认为private类型

    当类中已存在方法实现时,编译器不会生成对应的方法,且如果类中set和get方法同时存在时,编译器将不会自动生成speed变量

    @property细节

    默认情况下,自动生成的set和get方法访问带下划线_的成员变量

    万能指针-id

    OC中,id为万能指针,可以指向任何对象。

    本质:id相当于(NSObject *)

    [objc] view plaincopy
     
    1. id a=[Car new];     //定义了一个指向车对象的指针a  

    构造方法

    1. 基本概念

    构造方法:用来初始化对象成员变量的方法,是一个对象方法。

    构造方法init存在于NSObject类中

    2. 重写构造方法和自定义构造方法

    • 重写构造方法:

    目的:为了让对象一创建出来,成员变量就有一些固定的值

    Person类中:

    [objc] view plaincopy
     
    1. - (id) init  
    2. {  
    3.         //重写父类NSObject中init方法前,必须先调用父类init方法初始化父类中的一些成员变量和其他属性  
    4.         if(self=[super init])  
    5.         {  
    6.                 _age=10;  
    7.         }  
    8.         return self;  
    9. }  
    • 自定义构造方法:

    目的:可以在自定义一些值,使对象一创建出来,成员变量就拥有这些值

    Person中:

    [objc] view plaincopy
     
    1. //自定义初始化方法,使人对象一创建出来,就拥有名字和年龄  
    2. - (id)initWithName:(NSString *) name andAge:(int) age  
    3. {  
    4.          //必须先调用[super init];  
    5.          if(self=[super init])  
    6.          {  
    7.                   _name=name;  
    8.                   _age=age;  
    9.          }  
    10.          return self;  
    11. }  
    • 子类自定义构造方法

    Student中(此类继承Person类,_name及_age变量继承之Person,_no为Student自身变量):

    [objc] view plaincopy
     
    1. //自定义初始化方法,使学生对象一创建出来,就拥有名字、年龄和学号  
    2. - (id)initWithName:(NSString *) name andAge(int) age andNo(int)no  
    3. {  
    4.          //调用父类的initWithName: andAge方法,将传进来的name和age交给父类处理  
    5.          if(self=[super initWithName: name andAge: age])  
    6.          {  
    7.                   _no=no;  
    8.          }  
    9.          return self;  
    10. }  

    总结:谁的成员变量,调用谁的自定义构造方法进行初始化

    分类(Category)

    分类作用:在不改变原来类内容的前提下,为类增加一些方法

    基本介绍

    分类定义:

    //声明

    @interface 类名(分类名称)

    @end

    //实现

    @implementation 类名(分类名称)

    @end

    [objc] view plaincopy
     
    1. //创建类Person的分类  
    2. #import "Person.h"  
    3. //分类声明  
    4. @interface Person (PersonOther)  
    5.   
    6. @end  
    7.   
    8. #import "Person+PersonOther.h"  
    9. //分类实现  
    10. @implementation Person (PersonOther)  
    11.   
    12. @end  

    分类使用注意:

    • 分类只能增加方法,不能增加成员变量

    • 分类方法实现中可以访问原来类中声明的成员变量(除private外都可访问)(编程测试是否能访问@property编译自动生成的成员变量---已测不能访问)

    • 分类可以重新实现原来类中的方法,但是会覆盖调原来的方法,导致原来方法无法使用(一般不建议这样写)。

    • 编译运行时方法调用优先级:分类->原来类->父类

    • 一个类有多个分类时,优先级由编译器编译顺序决定

    利用分类给系统自带的类增加方法

    目前学到的系统的类有:NSString、NSObject

    例:给NSSring添加类方法和对象方法

    [objc] view plaincopy
     
    1. //给NSString添加计算字符串中数字个数的对象方法和类方法  
    2. #import <Foundation/Foundation.h>  
    3.   
    4. @interface NSString (NSStringOther)  
    5. //对象方法声明  
    6. - (int)stringOfNumCount;  
    7. //类方法声明  
    8. + (int)stringOfNumCount:(NSString *)str;  
    9. @end  
    10.   
    11. #import "NSString+NSStringOther.h"  
    12.   
    13. @implementation NSString (NSStringOther)  
    14.   
    15. //对象方法实现  
    16. - (int)stringOfNumCount  
    17. {  
    18.     int count=0;  
    19.     for (int i=0; i<self.length; i++) {  
    20.         if ([self characterAtIndex:i]>='1'&&[self characterAtIndex:i]<='9') {  
    21.             count++;  
    22.         }  
    23.     }  
    24.     return count;  
    25. }  
    26.   
    27. //类方法实现  
    28. + (int)stringOfNumCount:(NSString *)str  
    29. {  
    30.     int count=0;  
    31.     for (int i=0; i<str.length; i++) {  
    32.         if ([str characterAtIndex:i]>='1'&&[str characterAtIndex:i]<='9') {  
    33.             count++;  
    34.         }  
    35.     }  
    36.     return count;  
    37. }  
    38. @end  

    注意:

    OC中字符串@”zhang123”就是一个对象,可以[@”zhang123” 对象方法]直接调用对象方法

    类的本质

    • 类的本质:类本身也是一个对象,是一个Class类型的对象,简称类对象
    • 类的深入研究---类对象的使用

    利用类对象调用class方法创建类

    例:Person类

    Class c=[Person class]; 则:c现在就等价于Person类

    注意:Class本身就包含星号 *

    也可以利用Person的实例对象调用class方法创建类

    例:Person *p=[[person alloc] init];

    Class c1=[p class];     则:c1现在也等价于Person类

    • 类的深入研究---类的加载和初始化

    程序一旦启动,就会加载项目中所有的类和分类(加载:自我认为是给类分配内存空间?),而且加载后会调用所有类和分类的+load方法

    当第一次使用某个类时,就会调用当前类的+initialize方法(只有第一次会调用,只调用一次)

    总是先加载父类,再加载子类(先调用父类的+load方法,再调用子类的+load方法)一定发生

    总是先初始化父类,再初始化子类(先调用父类的+initialize方法,再调用子类的initialize方法)用才初始化,当然如果用子类则父类也一定会先初始化,只用父类时,子类并不初始化

  • 相关阅读:
    dp第三题
    近期(2012/5/15)
    HTML5 地理位置定位(HTML5 Geolocation)原理及应用【转】
    xml 中如何正确使用 & 符号
    Python进阶07 函数对象【转】
    Android 快捷小工具
    解决数据库乱码问题【转】
    Android APK反编译详解(附图)
    字符串转日期【20080808080808】
    HTML+5+从入门到精通
  • 原文地址:https://www.cnblogs.com/yaochao/p/4033650.html
Copyright © 2020-2023  润新知