文档章节

黑马程序员-7-Objective-C学习笔记(OC对象深入认识)

 明天过后1
发布于 2014/10/02 00:45
字数 2572
阅读 50
收藏 0

---------------------- Java培训.Net培训Android培训IOS培训、期待与您交流! ---------------------- 

1. 继承

    a. 继承的简介

           (1) 继承是什么

                    面向对象语言继承语法是比不可少的。那么日常生活中的继承意思就是把父一代的所有东西保留下来。在OC中继承也是这个意思,不过类之间的继承是把父类的属性和方法都继承下来,另外子类再有选择地扩展自己的功能。

                    继承在OC中无处不在,我们知道创建一个OC对象必须继承与NSObject,因为NSObject是OC面向对象的特性的基类。

                    OC中只支持单继承,并不像C++那样可以继承多个父类。

            (2) 继承简单使用

    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject                // 冒号是继承语法的关键符号
                                                // Person是NSObject的子类(subclass),NSObject是Person的父类(superclass)
    code ...;
   
    @end;
    
    /*
    OC只支持单继承,因此以下写法错误
    @interface GoodStudent : Person ,Student
    
    ..code..;
    
    @end
    */

        (3) 继承的利弊   

            1) 好处         

                  继承带来的最大的好处是代码可重复利用,并可以根据需要扩充方法。

                  建立了类之间的联系,有利于提高代码的可读性(在考虑类之间使用组合关系还是继承关系要看类之间的逻辑关系是什么)。

                  有利于公共代码的抽取。如果某一些类他有很多种形态,但他们都有共同的特征,那么这时候就可以用继承关系把他们的共同特征抽取到父类中,遇到特殊需求要更改共同特征只需要把父类该了就行了。

            2) 坏处

                两个类之间的耦合性增强了。如上例,如果再增加一个Student类继承于Person那么Student就不能离开Person类而独立存在。

        (4) 继承注意点 :

            1) 子类的属性名称不能跟父类的属性名称相同

            2) 子类如果有跟父类一样的方法子类的方法会覆盖父类的方法,在对象调用该方法的时候会调用子类的方法。

    b. 多态

      (1)  在其他面向对象语言中谈到继承我们很容易就联想到多态这个概念:某一种事物具有多种形态。

        (2) 多态利用父类类型指针调用子类方法的过程其实是一种动态绑定的过程 : 在运行时根据对象的类型确定动态调用的方法

        (3) 好处 : 节省代码,如果某一个方法中接收的参数类型要求是具有某种特征的类的话使用多态特性可以一劳永逸

        (3) 坏处 : 不能利用父类指针来访问子类属性。

        //////////////////////Person类///////////////////////////////////////////////
        
        // Person.h
        #import <Foundation/Foundation.h>
        @interface Person : NSObject                
        {
            int _age;
        }                                        
        setter getter ...;
        @end;
        
        // Person.m
        #import "Person.h"
        @implementation Person
        setter getter..
        @end
        
        //////////////////////Student类///////////////////////////////////////////////
        #import "Student.h"
        @interface Student: Person              
        {
            NSString *_name;
        }                                        
        setter getter ...;
        @end;
        
        // Student.m
        #import "Student.h"
        @implementation Person
        setter getter..
        @end
        
        //////////////////////main///////////////////////////////////////////////
        int main(){
            @autoreleasepool{
                Person *p = [[[Student alloc] init] autorelease]; // 多态就是可以用父类类型指针指向子类对象,并可以用父类指针调用子类方法
                [p setAge:22];                                    // 在调用过程中只关心指针在内存中指向的是什么对象,p指向Student对象,Student继承与Perosn拥有Person类的方法
                [p setName:@"mike"];                              // 多态可以利用父类类型指针调用子类的方法,因为在内存中该指针指向的是Student对象
            }
            
            return 0;
        }


2. id类型

   (1) 一个类的实例化我们通常都是利用多态来调用NSObject的alloc和ini方法打开NSObject的头文件发现init返回的是id类型的数据。

   (2) 在OC中我们知道id是一个可以指向任何对象的万能指针,那么他具体如何声明?

        打开源码 :

    struct objc_object {
        Class isa  OBJC_ISA_AVAILABILITY;
    } *id;

    (3) 通过发现我们知道对象的本质一个结构体。

    (4) 那么这个id类型有什么用?

            1) 既然OC有多态的特性那么,在多态中可以使用id类的变量作为方法的参数

            2) 为了更好的结合id类型发挥多态的好处,通常会使用协议(后面会详细讨论)这个特性来限制id的方法。


3. 类的构造方法

    (1) OC中构造方法的概念      

        在java中构造方法是实例化一个对象的方法,而在OC中是由[NSObject new] == [[NSObject alloc] init]引申出来的一种新概念 : 就是重写 init 方法来完成对象初始化,但要注意的是重写方法中一定要调用父类的init方法:[super init]。

    (2) 构造方法的命名规范

            1) 构造方法是类方法

            2) 为了好区分构造方法和完善继承的问题,构造方法 命名规范 和 方法体定义如下 :

        + (id) initWith:(X)x and:(Y)y
        {
            id obj = [[super alloc] init];                // 一定要调用父类的初始化方法
            [obj setX:x];
            [obj setY:y];
            return obj;
        }

    (3) 使用构造方法的好处 : 有了构造方法我们就可以在构造方法中完成对象的初始化和属性的赋值,在调用过程中简化代码。


4. 对象的方法调用细节

    a. SEL

        oc对象方法的调用是基于消息机制的,那么这种消息究竟是怎么样的?打开源码我们可以得到SEL的原型

        // SEL的原型
        typedef struct objc_selector *SEL;

            SEL在类中无处不在,我们可以通过在类的方法体内通过 _cmd 来获得该方法的SEL指针:

        @implementation Person
        - (int)age
        {
            SEL getter = _cmd;
            return _age;        
        }
        @end

    b. 调用对象调用的原理

            (1) 猜测

                我们知道OC是一种建立在C语言基础指向的面向对象语法,调用对象方法的关键符号是 [obj sel]; 我的猜测是OC已经对 [ ] 进过过运算符的重载了,然后通过该重载函数实现消息机制。

            (2) 调用方法原理 : 

                [obj sel]; // 调用过程分两步:

                1) 先吧方法名和参数包装成SEL,然后通过该对象的isa指针发送消息调用相应的方法。

             (3) 调用的细节过程 :  方法调用的原理:其实每个类加载到内存中对象的方法都会封装成一系列的SEL列表,SEL会保存着这个方法的信息(当然包括方法的内存地址),当要调用该方法的时候,对象会通过isa指针找到内存中对应的                    方法的内存地址然后再调用该方法,在找到该方法之后该类对象会把该SEL放入缓存中,以便第二次寻找的时候提高效率


5. 点语法

    OC为了使其他语言的程序员快速入门提供的点语法特性

    a. 点语法是什么 和 使用方法

        (1) 点语法其实是对象的setter 和 getter的替代

        (2) 点语法是如何区分调用的是setter还是getter :

    /*
        区分的最好方法是看是否有返回值:
            需要返回值 --> getter
            需要参数   --> setter
    */
    Person *p = [[Person alloc] init];
    p.age = 20;        // setter == [p setAge:20]
    int age = p.age;   // getter == int age = [p age];
    NSLog(@"age is %d",p.age); // getter

    b. 使用注意

        点语法调用的方法跟属性名称无关只关心方法名

    @interface Person : NSObject
    
    - (void) setAge:(int)age;                // p.age = 20;   如果 - (void) setAgeless:(int)age;  p.ageless = 20
    - (int) age;                             // int age = p.age; 如果 - (int) ageless;  int age = p.ageless;
        
    - (void) setName:(NSString *)name;       // p.name = @"mike";
    - (NSString *)name;                      // NSString *name =p.age;
    @end


4. 类的本质

    a. 对象创建过程

           (1) 我们知道一个对象创建通常都是由以下语句产生 : Object obj = [[Object alloc] init];从表达式可以看到对象产生过程大概经历2步 (a) 内存空间分配 (2) 类的初始化

           (2) 从上述表达式对象是由类的类方法产生的。

           (3) 对象的属性和方法是如何存放 : 

                1) 每个对象在产生的时候都会分配一个 isa(Class类型) 指针指向类对象

                2) 对象的属性跟对象放在同一块内存空间内

                3) 对象的方法存放在类对象里

    b. 对象方法调用过程

            (1) 首先会把方法封装成SEL发送给类对象,

            (2) 类对象会根据该SEL找到相应的SEL列表然后遍历该列表然后找到该方法内存地址

            (3) 然后把该方法内存地址放进缓存里,以便下一次调用提高效率

            (4) 调用该方法返回相应的值

    c. 类对象产生的过程

        既然对象是由类对象产生的,那么类对象就存在于内存中,那么类对象是什么时候加载到内存中:

              (1) 在程序启动过程中会把所有类加载以便调用该类的 +load 方法(先调用父类的+laod方法,然后再调用子类的)而且 只会调用一次, 用来监听类的加载完毕 ------ 在程序启动时候执行的

              (2) 我们可以控制他们的加载顺序 : Build Phases --> Compile Sources  改变文件的顺序来改变加载顺序

              (3) 在类的第一使用时候会回调他的 +initialize 方法,而且先调用父类的 +initialize 方法 再调用子类的 +initialize -------- 在类的第一使用的时候执行

              (4) 我们可以利用 +load 和 +initialize 方法来完成一些我们想做得事。


5. description方法使用

            description方法是用来方便与NSLog方法来输出类个对象的描述,它使用的占位符为 %@ 

    a. + (NSString *) description 和 - (NSString *) description   

            这个方法是用来输出对 类 和 对象 的描述信息,我们可以重写该方法  : 

    // Person.m
    #import "Person.h"
    
    @implementaion Person
    
    + (NSSting *) description
    {
        return @"这是一个Person类";
    }
    
    - (NSString *) description
    {
        return @"这是一个Person对象";
    }
    @end
    
    // main.m
    
    #import "Person.h"
    
    int main()
    {
        Person *p = [[Person alloc] init];
        NSLog(@"%@",p); // 这是一个Person对象
        NSLog(@"%@",[p class]); // 这是一个Person类
        return 0;    
    }



---------------------- Java培训.Net培训Android培训IOS培训、期待与您交流! ---------------------- 

 详情请查看:http://edu.csdn.net/heima



© 著作权归作者所有

共有 人打赏支持
粉丝 2
博文 23
码字总数 36166
作品 0
佛山
私信 提问
Objecitive-C中的nil

当我学习OC的时候,我总是忍不住在对比。Actionscript是如何实现,而oc又是如何实现。这不,碰到nil的时候我发现了很大的不同之处。做个笔记。 在as中,如果将一个对象置为null,相当于空指针...

ChildhoodAndy
2013/03/21
0
3
聊聊 iOS 开发

做开发到一定程度后就会面临“转职”,是转向更深的技术还是工程管理值得考虑啊。。 行业现状 虽然近几年有大量的开发者涌入移动端,社会上的各种培训机构也越来越多,但是优秀的 iOS 开发者...

zhangao0086
2015/04/24
0
0
【iOS开发干货】Objective-C基础知识点总结(一)

长文,建议跳跃选择性阅读,大约10min可以读完全文。 iOS开发 1.目录 1.个人学习建议 2.知识点整理 3.下集预告 iOS这一行,都过了这么多年,还是水分很足,没有几个愿意安安心心查资料写东西...

曹真
2017/06/21
0
0
iOS开发初学者如何入门?

iOS开发初学者如何入门? 现在如何学习iOS开发成为很多人的疑问,事实上,并不是想象中的那样难,学习iOS开发从最根本的一点上去思考就是,把iOS培训的知识按区块分开,更加便于学习,现在很多...

红牛王
2017/05/23
59
0
IOS学习笔记——Objective-c基础(一)

最近自学ios,ios的支持语言是Objective-c,所以要学习ios就需要先学习Objective-c语言。当掌握了Objective-c的基础知识之后,我们就可以入手学习iOS开发做出一些自己的应用。 我现在还是...

丛林迷雾
2012/12/30
0
1

没有更多内容

加载失败,请刷新页面

加载更多

腾讯与Github的魔幻会面背后的故事…

10月22日,腾讯开源管理办公室有幸邀请到Github新晋CEO Nat Friedman,前来鹅厂参观交流。目前腾讯已经有近70个项目在Github上开源,共获得17w stars,世界排名11位。Github是腾讯开源的主阵...

腾讯开源
32分钟前
1
0
单例模式

单例模式(Singleton pattern)属于创建型设计模式。 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对...

NinjaFrog
37分钟前
1
0
TypeScript基础入门之装饰器(三)

转载 TypeScript基础入门之装饰器(三) 继续上篇文章[TypeScript基础入门之装饰器(二)] 访问器装饰器 Accessor Decorator在访问器声明之前声明。 访问器装饰器应用于访问器的属性描述符,可用...

durban
54分钟前
2
0
spring5调研学习(转载)

Spring框架的新功能 这一章主要提供Spring框架新的功能和变更。 升级到新版本的框架可以参考。Spring git。 内容列表 Spring 5.x框架新的功能 Spring 4.x框架新的功能 Spring 3.x框架新的功能...

小海bug
今天
2
0
为何Spring框架能这么流行?

想要学习更多关于Spring框架在Java开发者中如此流行?看这篇文章可以学到更多! Spring框架特性 Spring是用于应用开发中的一款强大,轻量级框架。更广泛地说,你可以认为Spring框架是一个定义...

java知识分子
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部