码迷,mamicode.com
首页 > 编程语言 > 详细

oc语言学习之基础知识点介绍(二):类和对象的进一步介绍

时间:2015-11-17 16:59:33      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:

一、类、对象在内存中的存储

/*
 内存分区:
    栈:局部变量
    堆:程序员自己写代码申请开辟的  程序员自己维护,编译器现在帮我们自动优化了,它在合适的给我们加上了释放空间的语句,所以我们现在写的对象不会造成内存泄露

    全局区:所有的全局变量和静态变量
    常量区:所有的常量
    代码区:程序编译后的指令集

        类是模板,肯定需要存在内存里面,因为实例化对象的时候需要根据这个模板来创建,那么存在内存里面,存在哪呢??

       类模板存在:全局区!
       存的是:类的描述,还有所有的方法实现
 
        每个对象都会有一个系统给我们的isa指针,但是这个指针无法直接使用,指针指向的是它所属的类的地址。
 
        对象和类的原则:对象一定属于类。
        对象调用方法,步骤其实是 先从指针变量找到对象所在堆空间地址,然后再通过这个对象里存的isa指针找到类中存的方法,再执行 
*/

#import <Foundation/Foundation.h>

@interface Person : NSObject{
    
    @public
    NSString *_name;
    int _age;
}

-(void)sayHi;

@end

@implementation Person

//当类被加载的时候会调用这个方法
+(void)load{
    NSLog(@"Person类被加载了");
}

-(void)sayHi{
    NSLog(@"大家好,我叫%@,今年%d岁",_name,_age);
}

@end

int a = 10;


void test(){
    
    
}

@interface Dog : NSObject

@end

@implementation Dog

//当类被加载的时候会调用这个方法
+(void)load{
    
    NSLog(@"Dog类被加载了");
}


@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
       
        //验证类在全局区
        /*
        NSLog(@"全局a的地址:%p",&a);//0x100004700
        
        NSLog(@"类地址:%p",[Person class]); //0x100004688
        
        NSLog(@"%p","abc"); // 0x100003b6e
        
        NSLog(@"%p",test);//0x1000013d0
        */
        
        Person *p1 = [Person new];
        
        Person *p2 = [Person new];
        
        Person *p3 = [Person new];
        
        
        NSLog(@"类地址:%p",[Person class]);//0x1000046e0
        
        //因为下面的都是同一个类型。所以打印的isa地址都一样
        NSLog(@"p1->isa=%p", [p1 valueForKey:@"isa"] );//0x1000046e0
        
        NSLog(@"p2->isa=%p", [p2 valueForKey:@"isa"] );//0x1000046e0
        
        NSLog(@"p3->isa=%p", [p3 valueForKey:@"isa"] );//0x1000046e0
        Dog *js = [Dog new];
        //因为下面的和上面的那些对象不是同一个类型,所以isa地址肯定不一样
        NSLog(@"js->isa=%p",[js valueForKey:@"isa"]);//0x1000047f0

    }
    return 0;
}

    二、pragma的使用

/*
    方法和函数弹出式窗口,里面包含了所有的方法和函数的声明列表以及实现列表,通过点击它可以方便又快速的跳转到某一个方法或函数那。
 
 #pragma mark 分组名
        作用:是在方法和函数弹出式窗口中增加分组信息,方便你快速的找到某个方法或函数。
 
 #pragma mark - 分组名:
        作用:跟上面一样,但是会增加分隔横线,这样看起来更直观。

*/
#import <Foundation/Foundation.h>

@interface Person : NSObject

#pragma mark - 运动相关
-(void)run;
-(void)swimming;
-(void)playBasktball;
@end

#pragma mark - Person实现类

@implementation Person

#pragma mark - 运动实现
-(void)run{}

-(void)swimming{}

-(void)playBasktball{}
@end

    三、对象作为方法的参数和返回值

          1、对象作为方法的参数

/*
 有参数的方法:
    定义语法:  -(void)方法名:(参数类型)参数1 方法名2:(参数类型)参数2;
 把对象作为方法的参数:
        语法:--(void)方法名:(类名 *)参数1;
 
 调用:
            [对象 方法名:对象]
        例: [d displayPerson:p1];
 
 注意:
        C以前分值传递和引用传递,现在OC也是一样。
        所以也就是说,你把int char float 结构体变量 等等传给方法都是值传递。
        值传递:在方法内改变了形参的值,外面的实参不会改变。
        传递对象:是引用传递。
        引用传递:在方法内改变了形参的值,外面的实参也会发生改变。
 
*/

#import <Foundation/Foundation.h>


#pragma mark - Person类
@interface Person : NSObject{
@public
    NSString *_name;
    int _age;
}

@end

@implementation Person

@end

#pragma mark - Display类
@interface Display : NSObject

-(void)displayPerson:(Person *)p; //相当于这个方法需要传入一个Person对象

-(void)changePerson:(Person *)p;//改变Person对象的属性

-(void)changeInt:(int)number;

@end

@implementation Display
-(void)displayPerson:(Person *)p{
    
    NSLog(@"p->_name=%@  p->_age=%d",p->_name,p->_age);
}

-(void)changePerson:(Person *)p{
    p->_name = @"习大大";
    p->_age = 50;
}

@end

#pragma mark - Main函数
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //实例化Display对象
        Display *d = [Display new];
        
        //把对象作为方法的参数进行输出
        //实例化Person对象,名字叫p1
        Person *p1 = [Person new];
        
        p1->_name = @"周小帅";
        p1->_age = 16;
        
        //传进去的对象是什么,就会打印什么
        [d displayPerson:p1];//周小帅 16 
    }
    return 0;
}

          2、对象作为方法的返回值

/*
    方法定义:
            -(返回值类型)方法名:参数列表;
            -(int)
            -(char)
            -(int *)
            -(struct student)
            -(Person *) //相当于要返回一个Person类的对象
    语法:
        -(类名 *)方法名:参数列表
 
        -(Person *)creatPerson; //返回一个Person对象
*/
#import <Foundation/Foundation.h>

#pragma mark - Person类
@interface Person : NSObject{
    
    @public
    NSString *_name;
    int _age;
}

-(void)sayHi;

@end

@implementation Person

-(void)sayHi{
    
    NSLog(@"大家好,我叫%@,今年%d",_name,_age);
}

@end

#pragma mark - PersonFactory类

@interface PersonFactory : NSObject

/**
 *  这个方法返回一个Person对象
 */
-(Person *)creatPerson;

@end

@implementation PersonFactory

-(Person *)creatPerson{
    //new关键字无论何时都会开辟新的堆空间(新的对象)
    Person *p = [Person new];
    p->_age = 16;
    p->_name = @"周帅";
    return p; //你要Person对象,我的p刚好就是person对象,所以可以返回p
    //所以每次返回的地址都不一样
}

@end
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        PersonFactory *pf = [PersonFactory new];
        //creatPerson里面方法用了new,所以每次返回的都是新的对象
        //zs是一个Person对象,地址比如说是:0x11
        Person *zs = [pf creatPerson];
        //然后打印的是0x11地址里面存的成员数据,因为没有改过,所以打印的还是原来方法内改的值
        NSLog(@"zs->name=%@   zs->age=%d",zs->_name,zs->_age);//周帅  16
        //ls也一个Person对象,地址比如说是:0x12
        Person *ls = [pf creatPerson];
        //然后打印的是0x12地址里面存的成员数据,因为没有改过,所以打印的还是原来方法内改的值
        NSLog(@"ls->name=%@   ls->age=%d",ls->_name,ls->_age);//周帅  16
        //改的是0x11里面的数据
        zs->_name = @"苍苍苍";
        zs->_age = 15;
        //因为ls指向的0x12没改,所以打印的还是原数据
        NSLog(@"ls->name=%@   ls->age=%d",ls->_name,ls->_age);//周帅 16
        //因为zs指向的0x11里面的改了,所以打印的是改后的数据
        NSLog(@"zs->name=%@   zs->age=%d",zs->_name,zs->_age);//苍苍苍 15
    }
    return 0;
}

四、结构体作为类的成员

typedef struct {
    int year;
    int month;
    int day;
    
}myDate;

@interface Person : NSObject{
    @public
    NSString *_name;
    int _age;
    BOOL _gender;
    //出生年月日
    myDate _birthDay;
    //人可以养一条宠物
    Dog *_chongwu; //代表是Dog对象类型
}

/**
 *  说自己生日的
 */
-(void)sayMyBirthDay;
@end
@implementation Person
-(void)sayMyBirthDay{ NSLog(@"我出生于%d年%d月%d日",_birthDay.year, _birthDay.month,_birthDay.day); _chongwu->_color = @"黄色"; } @end /* 结构体也可以作为类的成员。 本身类的成员属性的定义语法就是 : 类型 成员变量名; 所以只要符合这个语法的都行! 所以换句话来说,所有只要是类型的东西,都可以作为成员属性 结构体作为对象的成员: 在对象内部:成员名.成员 例:_birthDay.year 在外部:对象名->成员名.成员 例: p->_birthDay.year */ #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { Person *p = [Person new]; p->_age = 16; // p->_birthDay.year = 1998; // p->_birthDay.month = 2; // p->_birthDay.day = 3; //一次性赋值,需要强转,右边的小括号里面必须加这个结构体的类型 p->_birthDay = (myDate){1998,12,3}; //实例化某个对象属性 p->_chongwu = [Dog new]; [p sayMyBirthDay]; NSLog(@"出生于哪年%d",p->_birthDay.year); //外部访问某一个属性(这个属性又是一个对象)的时候的赋值 p->_chongwu->_color = @"红色"; NSLog(@"养了条宠物,毛色是%@",p->_chongwu->_color); } return 0; }

五、多文件开发

/*
c语言中有多文件开发,oc中肯定也有。
多文件开发的原因:
        1.我们的类代码太多,写在一个文件里面不利于观察。
        2.项目是多个人一起开发的,如果写在一个文件里面不利于同时开发。
注意: 写好模块后,一定只能导入.h文件,不能导入.m文件。

多文件开发添加文件方式:鼠标右键,选择New File ,然后在选择Cocoa Class ,第一栏填名称,第二栏是表示继承哪里,一般情况下不需要修改,会自动穿件oc的头文件和.m文件。
*/

六、结构体与类的区别、函数与方法的区别

/*
结构体与类的区别:
    1.语法区别。
    2.结构体里面不能包含行为(方法、函数),类可以。
    3.结构体成员不能写访问修饰符,但是类可以。
    4.结构体里面不能有类的对象作为成员,但是类可以有结构体作为成员。
    5.结构体数据保存在栈,对象数据保存在堆。
    6.结构体是面向过程的思维产物,类是面向对象的思维产物。
 
函数与方法的区别:
        1.语法不同。
        2.函数可以直接调用,方法必须通过对象。
        3.函数的声明可以写在任意位置,不包括属性列表的大括号里面。方法的声明只能写在@interface和@end之间,不包括属性列表的大括号里面。
         4.函数的实现可以写在除了函数内的其他所有位置(不要写在@interface和@end之间),不包括属性列表的大括号里面,方法的实现只能写在@implementation和@end之间。
        5.函数是面向过程的思维,方法是面向对象的思维。
*/

七、NSString的略详细介绍

/*
 
 NSString 是OC中的字符串类型
 
    用法:
        NSString *str = @"字符串";
 
 
    1.NSString也是一个对象,所以也可以通过new来创建
 
    2.NSString按格式化组成一个字符串
 
                [NSString stringWithFormat:@"格式化字符串",值列表];
 
            例: NSString *str = [NSString stringWithFormat:@"哈哈,今年%d岁",16];
 
    3.OC中比较两个字符串是否相等:
 
        C语言:strcmp(字符串1,字符串2) == 0 代表相等;
 
        OC:[ OC字符串1 isEqualToString:OC字符串2]; 这个方法有一个BOOL类型的返回值,如果相等返回YES,否则返回NO
 
        例:[str1 isEqualToString:str2]
 
        注意:也可以直接把这个方法调用写在if括号里面判断
 
 
    4.OC字符串怎么计算实际个数??(重点)
        C语言:strlen(字符串);  计算实际占用的字节数
 
        OC语言:[OC字符串 length]; 返回这个OC字符串的实际个数
        
        例:[str length];
 
*/

#import <Foundation/Foundation.h>

@interface Person : NSObject{
    
    @public
    int _age;
}
@end

@implementation Person


@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //不用这种写法,因为这种对象主要是用来表示一个字符串
//        NSString *str = [NSString new];
//        str = @"字符串";
        
        //直接这么用就行
//        NSString *str = @"字符串";
//        
//        NSLog(@"%@",str);
          //格式化字符串//        NSString *str = [NSString stringWithFormat:@"哈哈,今年%d岁",16];
//        
//        NSLog(@"%@",str);
        
        //判断两个字符串是否相等
        /*
        NSString *str1 = @"哈哈";
        NSString *str2 = @"哈哈";
        
        BOOL res = [str1 isEqualToString:str2];
        
        if (res) {
            
            NSLog(@"相等");
            
        }else{
            
            NSLog(@"不相等");
        }
        */
        
        /*
        BOOL res = [@"哈哈" isEqualToString:@"哈哈"];
        
        if (res) {
            NSLog(@"相等");
        }else{
            NSLog(@"不相等");
        }
        */
        
        //获得OC字符串的实际个数
        NSString *str = @"abcd 哈^";
        unsigned long length  = [str length];
        NSLog(@"%lu",length);//7个 空格、符号等等都算
        unsigned long length2  = [@"呵呵呵" length];
        NSLog(@"%lu",length2);//3个

    }
    return 0;
}

 

 

oc语言学习之基础知识点介绍(二):类和对象的进一步介绍

标签:

原文地址:http://www.cnblogs.com/bobo-pcb/p/4972037.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!