黑马程序员————IOS学习笔记 第6篇 OC特殊语法(2)

来源:互联网 发布:车身设计 知乎 编辑:程序博客网 时间:2024/06/02 06:02

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

一、构造方法

    在之前的学习的[Person new]可以创建一个类 并且能够初始化对象,实际在开发中new不常用,通常情况下用构造的方法来对成员变量初始化。

1. 完整的创建一个可用的对象分为两步

第一步:分配存储空间    调用的是+alloc方法

第二步:.初始化   -init

[person new]拆分后是:

Person *p1 = [Person alloc];

Person *p1 = [p1 init];

合成一句后:

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

2.init方法的重写过程:

  有时候new给出的初始值并不是所需的值,因此要用到构造方法,用来初始化对象的方法,因此要重写-(id)init,它是NSObject类中的对象方法

在NSObject类中的init初始化过程:
1.一定要调用super类的init:初始化父类中声明的成员变量和其他属性  self=[super init]  然后返回一个对象给self 当前对象   初始化父类声明中的成员变量
2.'如果初始化成功,才对当前的对象进行自己所规定的变量进行初始化
3.返回一个已经初始化话完毕的对象

在类中重写init也要遵循NSObject中的过程:

- (id)init

{

if (self = [super  init])

    {

_age = 10;

    }

return   self;

}

 注意:

init 初始化的顺序是:NSObject    父类    子类

3.自定义的构造方法

       有时想要随时修改初始值,那么就不能重写构造方法,而是要自定义构造方法,这样可以使外部能够灵活改变初始化的值。原则:对于自己的属性就由自己处理,父类有的

属性就交给父类处理,可以避免父类中的东西修改对子类无影响。

  注意:

 1.一定是对象方法,一定以 - 开头

 2.返回值一般是id类型

 3.方法名一般以initWith开头

- (id)initWithAge:(int)age{

if (self = [super init] {

       _age = age;

    }

return self;

}

person.h

#import <Foundation/Foundation.h>@interface Person : NSObject@property NSString *name;@property int age;- (id)initWithName:(NSString *)name;- (id)initWithAge:(int)age;// initWithName:andAge:- (id)initWithName:(NSString *)name andAge:(int)age;@end
person.m

#import "Person.h"@implementation Person- (id)init{    if ( self = [super init] )    {        _name = @"Jack";    }    return self;}- (id)initWithName:(NSString *)name{    if ( self = [super init] )    {        _name = name;    }        return self;}- (id)initWithAge:(int)age{    if ( self = [super init] )    {        _age = age;    }    return self;}- (id)initWithName:(NSString *)name andAge:(int)age{    if ( self = [super init] )    {        _name = name;        _age = age;    }    return self;}@end

student.h

#import "Person.h"@interface Student : Person@property int no;- (id)initWithNo:(int)no;- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no;@end
student.m

#import "Student.h"@implementation Student- (id)initWithNo:(int)no{    if ( self = [super init] )    {        _no = no;    }    return self;}// 父类的属性交给父类方法去处理,子类方法处理子类自己的属性- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no{    // 将name、age传递到父类方法中进行初始化    if ( self = [super initWithName:name andAge:age])    {        _no = no;    }        return self;}

main.m

#import <Foundation/Foundation.h>#import "Person.h"#import "Student.h"int main(int argc, const char * argv[]){    @autoreleasepool {        Student *p = [[Student alloc] initWithName:@"Jim" andAge:29 andNo:10];        NSLog(@"00000");    }    return 0;}

注意在以上的实例中:

对于student类中如果也对age name 这两个属性进行直接初始化是不恰当的(如以下代码):

- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
{     if ( self = [super init] )     {                  self.name = name;         self.age = age;                 //[self setName:name];         //[self setAge:age];     }      return self;}

二、分类

    category 依赖于类 ,可以便于模块开发,增加开发的灵活,如多个人共同开发同一个类。通常情况下想要扩充类的方法,可以重新修改类增加方法,可以用继承,但是除了这

两种方法外,还可以在不改变原来类的基础上扩充方法,就是分类。

1.格式:

分类的声明

@interface类名 (分类名称)

// 方法声明

@end

分类的实现

@implementation类名 (分类名称)

// 方法实现

@end

2.分类的应用:

扩展NSTring类,从下面的例子可以感受到分类的好处 ,一个庞大的类可以分模块开发,可以由多个人来编写,更有利于团队合作。

 给NSString增加一个类方法:计算某个字符串中阿拉伯数字的个数
 给NSString增加一个对象方法:计算当前字符串中阿拉伯数字的个数

NSTring+Number.h

#import <Foundation/Foundation.h>@interface NSString (Number)+ (int)numberCountOfString:(NSString *)str;- (int)numberCount;@end
NSTring+Number.m

#import "NSString+Number.h"@implementation NSString (Number)//  @"abc434ab43"+ (int)numberCountOfString:(NSString *)str{    // 1.定义变量计算数字的个数//    int count = 0;//    //    for (int i = 0; i<str.length; i++)//    {//        unichar c = [str characterAtIndex:i];//        //        if ( c>='0' && c<='9')//        {//            count++;//        }//    }//    return count;        return [str numberCount];}- (int)numberCount{    int count = 0;        for (int i = 0; i<self.length; i++)    {        // 取出i这个位置对应的字符        unichar c = [self characterAtIndex:i];                // 如果这个字符是阿拉伯数字        if ( c>='0' && c<='9' )        {            count++;        }    }        return count;}@end

3.注意:

分类单独放在一个文件里跟之前创建一个新类一样,分类的声明放在.h,分类的实现放在.m文件

分类可以访问原始类的实例变量,但不能添加变量,只能添加方法。如果想添加变量,可以考虑通过继承创建子类

可以实现原始类的方法,但不推荐这么做,因为它是直接替换掉原来的方法,这么做的后果是再也不能访问原来的方法

多个Category中如果实现了相同的方法,只有最后一个参与编译的才会有效

分类的优先级高于原来的类,在调用方法时,优先到分类中去查找,然后再去原来的类中找,之后再去父类中找。

若方法重写方法调用的优先级:分类(最后参与编译的分类优先)—>子类—>父类


三、类的本质

1.本质

   类其实类也是一个对象,是Class类型的对象,简称“类对象”

    Class类型的定义:typedef  structobjc_class *Class;

     类名就代表着类对象,每个类只有一个类对象

2 .+load

   在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法

   先加载父类,再加载子类;也就是先调用父类的+load,再调用子类的+load

   先加载元原始类,再加载分类

    不管程序运行过程有没有用到这个类,都会调用+load加载

 3.  +initialize

在第一次使用某个类时(比如创建对象等),就会调用一次+initialize方法

一个类只会调用一次+initialize方法,先调用父类的,再调用子类的

4.获取类对象的2种方式

Class c = [Personclass];// 类方法

或者

Person*p = [Personnew];

Class c2 = [p class];// 对象方法

5.类对象调用类方法

Class c = [Person  class];

Person *p2 = [c new];

四、description方法

     使用NSLog和%@输出某个对象时,会调用对象的-description方法,并拿到返回值进行输出。NSLog(@"%@",p)默认情况下输出对象时结果是 :类名:内存地址,如果想把一个对象属性输出,就要重写description 。修改NSLog的默认输出,重写-description或者+description方法即可。

1.+description重写:

+ (NSString *)description
{
    return @"Abc";
}

那么在test2函数执行后就会输出Abc

void test2()
{
    Class c = [Person class];
    
    // 1.会调用类的+description方法
    // 2.拿到+description方法的返回值(NSString *)显示到屏幕上
    NSLog(@"%@", c);
}

2.NSLogs输出补充:

// 输出当前函数名
    NSLog(@"%s\n", __func__);

// 输出行号
    NSLog(@"%d", __LINE__);
    
 // NSLog输出C语言字符串的时候,不能有中文

    NSLog(@"%s", __FILE__);若文件名是中文就无法输出要使用    printf("%s\n", __FILE__);

// 指针变量的地址
    NSLog(@"%p", &p);

// 对象的地址
    NSLog(@"%p", p);

 // <类名:对象地址>
    NSLog(@"%@", p);


0 0
原创粉丝点击