美文网首页
oc 语言知识点

oc 语言知识点

作者: 一直很安静_25ae | 来源:发表于2019-05-30 13:42 被阅读0次

    一: 类的合理设计

    //定义枚举

    typedef enum {

        SexMan,

        SexWoman

    }Sex;

    //定义结构体

    typedef struct{

        int year;

        int moonth;

        int day;

    } Date;


    二:成员变量的命名规范

         一定要以下划线_开头

    作用:

        1>让成员变量个get方法的名称区分开

        2>可以跟局部变量区分开,一看到下划线开头的变量,一般都是成员变量


    三:iOS的方法只有类方法和对象方法 (可以允许类方法和对象方法同名 虽然同名但是类方法是加好开头对象方法是减号开头)

    对象方法:

        1>减号-开头

        2>只能由对象来调用

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

    类方法

        1>加号+开头

        2>只能由类(名)调用

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

    类方法的好处和使用场合

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


    四:self的用途

        1>self指向了当前对象(方法调用者)

                谁调用了当前方法,self就代表谁

                self出现在对象方法中,self就代表对象

                self出现在类方法中,self就代表类

        2>可以利用self->成员变量名 访问当前对象内部的成员变量

        3>[self 方法名]可以调用其他对象方法\类方法


    五:封装

        工具类(封装类方法):特点基本没有任何成员变量,里面的方法基本都是类方法


    六:继承和组合

    继承:

        子类继承父类,相当于拥有了父类里面的多有成员变量和方法

        不允许子类和父类拥有相同名称的成员变量

        允许子类拥有和父类一样的方法(相当于重写了父类的方法)

       6.1 重写:

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

        注意:

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

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

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

    6.2组合

        继承和组合的选择    

        继承的使用场合: 

                1>当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中    

                2>当A类完全拥有B类中的部分属性和方法时,就可以考虑让B类继承A类

        继承是 xx是xxx          举例 狗是动物

        组合是xxx拥有xxx     举例 人拥有狗


    七:多态

                多态就是父类指针指向子类对象

                举例: 假设动物Amimal是父类 dog是继承与Amimal的子类  Amimal *animal =  [dog  new];    [animal  eat];但是在调用方法的时候,系统会动态监测对象的真实形象 animal这个对象其实是一个狗对象 


    八:点语法

    oc的点语法其实就是调用的get或者set方法(点语法 的本质还是方法调用)

    8.1 死循环注意

    举例 写一个年龄age的set和get方法中引起的死循环

    - (void)setAge:(int)age{

    _age  = age;//这是可以的

    self.age = age;//这就会引起死循环 相当于 [self setAge:age];

    }

    - (int)age{

    return _age;//这是可以的

    return self->age;//这也是可以的

    return self.age; //这就会引起死循环 相当于 [ self age];

    }


    九:成员变量的作用域

        9.1 类型

        1>@private 只能在当前类的实现@implementation中直接访问

        2>@protect 可以在当前类以及子类实现@implementation中直接访问 (默认就是@protect)

        3>@public 任何地方都可以访问对象的成员变量

         4>package 同一个"体系内"(框架)可以访问介于@private和 @public    之间   

        9.2

     @implementation中定义的成员变量默认都是私有的,只能在当前类的实现中使用,但不能定义和@interface中同名的成员变量

     @implementation中定义的成员变量默认都是私有的,通过添加@public 可以被外界访问,但是最好不要这样写    


    十:@property

    10.1 @property (IOS 4.0之前)

        作用:可以自动生成某个成员变量的setter和getter方法的声明

        @synthesize (IOS 4.0之前)  @synthesize  age = _age;

        作用:可以自动生成某个成员变量的setter和getter方法的实现,并且会访问下划线_age这个成员变量,如果成员变量不存在就会自动生成一个私有的@private成员变量age (此处age是为了举例说明)

    如果手动实现了setter方法,则编译器只会自动生成getter方法

    如果手动实现了getter方法,则编译器只会自动生成setter方法

    10.2@property (IOS 4.0之后)

        @property 就独揽了@synthesize 的功能,也就是说@property 可以同时生成getter和setter的声明和实现,默认情况下,getter和setter方法中的实现会去访问下划线_开头的成员变量


    十一:id

        简介:id是万能指针,指向任何oc对象,相当于NSObject *

        使用: id p = [Person new]; //注意id后面不能加*

        连接地址:https://www.jianshu.com/p/19f9e73f7d8f


        id:是一种数据类型;

    id类型被定义为指向对象的指针,这可以从id的定义中看出。id在objc.h中的定义为:

    typedef struct objc_object {

    Class isa;

    } *id;

    id是一个一个比较灵活的对象指针,并且是一个指向任何一个继承了Object(或者NSObject)类的对象。而在cocoa的开发环境里,NSObject是所有类的根类。所以id可以指向任何一个cocoa的合法对象。

    Objective-C中的id这种数据类型存在的价值是什么?

    id是一种通用的对象类型,她可以用类存储属于任何类的对象,可以理解为万能指针

    ***在id的定义中,已经包装好了*号,id指针只能指向os的对象

    NSObject 和id都可以指向任何对象

    NSObject对象会进行编译时检查(需要强制类型转换)

    id不需要强制类型转换,id可以直接使用

    编译器看到id以后,认为是动态类型,不在检查类型

    id类型:

    id是一个数据类型, 并且是一个动态数据类型

    既然是数据类型, 所以就可以用来

    1、定义变量

    2、作为函数的参数

    3、作为函数的返回值

    4、id==NSObject*  万能指针

    id和NSObject *的区别:

    NSObject*是一个静态数据类型id是一个动态数据类型默认情况下所有的数据类型都是静态数据类型

    静态数据类型的特点:

    1、在编译时就知道变量的类型,

    2、知道变量中有哪些属性和方法

    3、在编译的时候就可以访问这些属性和方法,

    4、如果是通过静态数据类型定义变量, 如果访问不了属于静态数据类型的属性和方法, 那么编译器就会报错   

    动态数据类型的特点:

    1、在编译的时候编译器并不知道变量的真实类型, 只有在运行的时候才知道它的真实类型

    2、如果通过动态数据类型定义变量, 如果访问了不属于动态数据类型的属性和方法, 编译器不会报错

    通过静态数据类型定义变量, 不能调用子类特有的方法

    通过动态数据类型定义变量, 可以调用子类特有的方法

    通过动态数据类型定义的变量, 可以调用私有方法

    弊端: 由于动态数据类型可以调用任意方法, 所以有可能调用到不属于自己的方法, 而编译时又不会报错, 所以可能导致运行时的错误

    应用场景: 多态, 可以减少代码量, 避免调用子类特有的方法需要强制类型转换

    为了避免动态数据类型引发的运行时的错误, 一般情况下如果使用动态数据类型定义一个变量, 在调用这个对象的方法之前会进行一次判断, 判断当前对象是否能够调用这个方法

    instancetype和id的区别:

    1、instancetype==id== 万能指针 == 指向一个对象

    2、id在编译的时候不能判断对象的真实类型

    3、instancetype在编译的时候可以判断对象的真实类型(一个在编译时不知道真实类型, 一个在编译时知道真实类型)

    4、id可以用来定义变量, 可以作为返回值, 可以作为形参

    5、instancetype只能用于作为返回值,它会进行类型检查,如果创建出来的对象,赋值了不相干的对象就会有一个警告信息,防止出错


    十二:构造方法

    简介:用来初始化对象的方法 

        在初始化的方法中一定要调用父类的[super init]方法(父类的属性交给父类的方法处理,子类方法处理子类自己的属性)如何完整的创建一个可用的对象 1:分配合理的存储空间 +alloc  2:调用-init进行初始化

    连接 https://www.jianshu.com/p/9d38caa5c98a


    构造方法  

    什么是构造方法:初始化对象的方法。

    一般情况下,在 OC 当中创建1个对象分为两部分(new 做的事):

    alloc:分配内存空间,init :初始化对象。

    构造方法分为系统自带和自定义构造方法。 

    (1)如果是系统自带的构造方法,需要重写父类中自带的构造方法 比如init 

    (2)如果是自定义构造方法:属于对象方法那么以-号开头,返回值一般为id或者instancetype类型,方法名一般以init开头  

    系统构造方法书写格式:

    - (instancetype)init{

    self= [superinit];

    if(self) {

            }

    returnself;

    }

    自定义构造方法:

    @property int age;

    @property NSString *name;//自定义构造方法 在初始化的时候为属性"年龄"和"姓名"赋值

    - (instancetype)initWithAge:(int)age andName:(NSString*)name;

    实现

    // 实现自定义构造函数 在初始化的时候为属性赋值

    - (instancetype)initWithAge:(int)age andName:(NSString*)name{

    if(self= [superinit]) {  

      _age = age;   

     _name = name;

    }

    return   self;

    }


    十三:分类

    分类的作用:在不改变原来类内容的基础上,可以为分类增加一些方法

    分类的使用注意:

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

    2>分类方法实现中可以访问原来类中声明的成员变量

    3>调用方法的时候会优先去分类中查找,然后再去原来类中查找,最后再去父类中查找

    方法调用的优先级 分类(最后参与编译的分类优先)>>原来类>>父类

    4>分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法没办法在使用(因为方法的调用顺序有优先级)


    十四:类 

    类本身也是一个对象(万物皆对象)是一个class类型的对象,简称类对象

    类对象 == 类

    创建类对象的两种方式 假设有个person类

    //第一种方法 利用class创建类对象

    class  c = [person  class];

    ///第二种方法 

    person *p1 =[ [person   alloc] init];

    class c = [p1   class];


    十五:+(void)load 方法  和+(void)initialize方法

    +(void)load 

        在类被加载的时候调用,也就是程序一启动这个方法就会被调用(不管程序运行过程中有没有用到这个类,都会调用+ load方法)

    +(void)initialize

        当第一次使用这个类的时候,就会调用一次+ initialize,并且只会调用一次这个方法

    总结:

    1>当程序启动的时候就会加载项目中的类和分类,而且加载后会调用"每个类和分类"的 + load 方法,并且只会调用一次(每一个都会调用)

    2>当第一次使用某个类的时候,就会调用当前的+ initialize方法和父类的+ initialize(当前的和父类的,也就是说子类的不会调用)

    3>先加载父类,在加载子类(先调用父类的+ load 方法,在调用子类的+ load 方法,先加载原始类,在加载分类)

        先初始化父类,再初始化子类(先调用父类的+ initialize方法再调用子类的+ initialize方法)


    十六: SEL

    1>方法的存储位置

        1.1 每个类的方法列表都存储在类对象中

        1.2每个方法都有一个与之对应的SEL类型的对象

        1.3根据一个SEL对象就可以找到方法的地址,进而调用方法

        1.4 SEL类型的定义

                 typedef struct objc_selectore   *SEL

    2>SEL对象的创建

    第一种:SEL s = @selector(方法名);

    第二种 SEL s = NSSelectorFromString(@"test");

    3>举例

    3.1举例 -----1

    Person *p = [[Person   alloc]init];

    [p  test];//假设Person 类中有一个test方法

    对象p调用test方法相当于(程序内部执行的实际为)

    [p performSelector:@selectore(test)];

    解释说明:

    1->把test包装成SEL类型的数据

    2->根据SEL数据找到对应的方法地址

    3->根据方法地址调用对应的方法

    3.2举例 ------ 2

    Person *p = [[Person   alloc]init];

    [p  test:@"123"];//假设Person 类中有一个test:方法

    对象p调用test方法相当于(程序内部执行的实际为)

    [p performSelector:@selectore(test:) withObject:@"123"];


    相关文章

      网友评论

          本文标题:oc 语言知识点

          本文链接:https://www.haomeiwen.com/subject/bbkenttx.html