美文网首页
Objective-C类和对象

Objective-C类和对象

作者: 橙子遇到八哥 | 来源:发表于2020-03-08 10:45 被阅读0次

    类和对象

    1. 类定义

    @interface Person : NSObject
    {
    }
    @end
    

    2. 成员变量

    @private
    NSString    *_name;  //在ObjC中推荐成员变量名以_开头
        int         _age;
    @protected
        NSString    *_nation;
    @public
        float       height;
    

    3. 方法和属性

    说明:参数类型、返回值类型需要放到()中、冒号是方法名的一部分
    h

    //声明一个动态方法,没有返回值
    -(void)setName:(NSString *)name;
    //声明一个静态方法,没有返回值
    +(void)showMessage:(NSString *)info;
    

    m

    #import "Person.h"
    @implementation Person
    
    
    //实现一个动态方法
    -(void)setName:(NSString *)name{
        _name=name;
    }
    //实现一个静态方法
    +(void)showMessage:(NSString *)info{
        NSLog(@"%@",info);
    }
    @end
    

    4. getter/setter

    //实现age的setter、getter方法
    -(int)age{
        return _age;
    }
    -(void)setAge:(int)age{
        _age=age;
    }
    

    5. 类的初始化和方法的调用

    Person *p=[Person alloc];
    p=[p init];
    //上面两句代码可以直接写成:Person *p=[[Person alloc] init];
    //还可以写成:Person *p=[Person new];
    
    //成员变量调用
    p->height=1.72;
    NSLog(@"height=%.2f",p->height);//结果:height=1.72
    
    //方法调用
    [p setName:@"Kenshin"];
    
    //属性调用
    p.age=28; //等价于:[p setAge:28];
    int age=p.age;//等价于:age=[p age];
    NSLog(@"age=%i",age); //结果:age=28
    

    6. @propert和@synthesize

    6.1 如果只声明一个属性a,不使用@synthesize实现:编译器会使用_a作为属性的成员变量(如果没有定义成员变量_a则会自动生成一个私有的成员变量_a;如果已经定义了成员变量_a则使用自定义的成员变量_a。注意:如果此时定义的成员变量不是_a而是a则此时会自动生成一个成员变量_a,它跟自定义成员变量a没有任何关系);

    6.2 如果声明了一个属性a,使用@synthesize a进行实现,但是实现过程中没有指定使用的成员变量(例如上面birthday):则此时编译器会使用a作为属性的成员变量(如果定义了成员变量a,则使用自定义成员变量;如果此时没有定义则会自动生成一个私有的成员变量a,注意如果此时定义的是_a则它跟生成的a成员变量没有任何关系);

    6.3 如果声明了一个属性a,使用@synthesize a=_a进行实现,这个过程已经指定了使用的成员变量:此时会使用指定的成员变量作为属性变量;
    有了上面的总结,相信理解上面的代码并不难,通常在实际开发过程中我们要么直接在@property中声明不使用@synthesize;要么使用过程中指定具体的成员变量。

    此外再次强调一下,通过上面的方式定义变量的本质还是生成对应的gettter、setter方法(只是这个步骤编译器帮你完成了),如果通过@property定义了属性,同时在.m中又自定义实现了对应方法,则会使用自定义方法。

    #import <Foundation/Foundation.h>
    #.h
    @interface Person : NSObject{
    }
    
    @property NSString *birthday;
    
    
    #.m
    #import "Person.h"
    
    @implementation Person
    
    @synthesize birthday;
    
    -(void)printInfo{
        NSLog(@"_birthday=%@",_birthday);
    }
    @end
    

    7. self

    self不仅可以表示当前对象还可以表示类本身,也就是说它既可以用在静态方法中又可以用在动态方法中。
    Perosn.h

    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    
    @property NSString *name;
    @property int age;
    
    -(void)setName:(NSString *)name andAge:(int)age;
    
    +(void)showMessage;
    @end
    

    Person.m

    #import "Person.h"
    
    @implementation Person
    -(void)setName:(NSString *)name andAge:(int)age{
        self.name=name;
        self.age=age;
    }
    
    +(void)printInfo{
        NSLog(@"Hello,World!");
    }
    
    +(void)showMessage{
        [self printInfo];
    }
    @end
    

    8. 构造方法

    Person.h

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

    Person.m

    #import "Person.h"
    
    @implementation Person
    
    //自定义构造方法
    -(id)initWithName:(NSString *)name andAge:(int)age{
        if(self=[super init]){ //super代表父类
            self.name=name;
            self.age=age;
        }
        return self;
    }
    
    @end
    

    9. 申请内存

    Person.h

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

    Person.m

    #import "Person.h"
    
    @implementation Person
    
    //自定义构造方法
    -(id)initWithName:(NSString *)name andAge:(int)age{
        if(self=[super init]){ //super代表父类
            self.name=name;
            self.age=age;
        }
        return self;
    }
    
    //通过静态方法获得一个对象
    +(id)personWithName:(NSString *)name andAge:(int)age{
        Person *p=[[Person alloc]initWithName:name andAge:age];
        return p;
    }
    @end
    

    main.m

    #import <Foundation/Foundation.h>
    #import "Person.h"
    
    int main(int argc, const char * argv[]) {
        
        Person *p=[[Person alloc]initWithName:@"Kenshin" andAge:28];
        NSLog(@"name=%@,age=%i",p.name,p.age);
        //结果:name=Kenshin,age=28
        
        Person *p2=[Person personWithName:@"Kaoru" andAge:27];
        NSLog(@"name=%@,age=%i",p2.name,p2.age);
        //结果:name=Kaoru,age=27
        return 0;
    }
    

    10. description方法

    在C#中每个类都有一个ToString()方法(java中叫做toString())用于打印一个对象的信息,在ObjC中这个方法叫description,例如在前面的Person类中我们可以重写这个方法用于打印调试
    Person.m

    #import "Person.h"
    
    @implementation Person
    
    -(NSString *)description{
        return [NSString stringWithFormat:@"{name:%@,age:%i}",self.name,self.age];
    }
    
    @end
    

    main.m

    #import <Foundation/Foundation.h>
    #import "Person.h"
    
    int main(int argc, const char * argv[]) {
    
        Person *p=[[Person alloc]init];
        p.name=@"Kenshin";
        p.age=28;
        
        NSLog(@"%@",p);//此时会调用对象description方法返回对应的描述信息
        /*结果:
         name:Kenshin,age:28}
         */
        
        return 0;
    }
    

    注意:上面NSLog中的格式符是%@,当使用%@输出一个对象时,ObjC会调用个对象的description返回对应的信息进行输出,默认情况下如果我们不重写description方法,输出内容是类名和地址,例如Person则输出“<Person: 0x100202310>
    需要强调的是千万不要在description中打印输出self,因为当输出self时会调用该对象的description方法,如此一来就会造成死循环。

    11. 继承

    Person.h

    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject{
        @protected
        NSString *_nation;
    }
    
    #pragma mark - 属性
    #pragma mark 姓名
    @property (nonatomic,copy) NSString *name;
    #pragma mark 年龄
    @property (nonatomic,assign) int age;
    #pragma mark 籍贯
    @property (nonatomic,copy) NSString *nation;
    
    #pragma mark - 动态方法
    #pragma mark 带有参数的构造函数
    -(id)initWithName:(NSString *)name andAge:(int )age;
    
    #pragma mark - 静态方法
    #pragma mark 通过静态方法返回一个对象
    +(id)personWithName:(NSString *)name andAge:(int )age;
    
    @end
    

    Person.m

    #import "Person.h"
    
    @implementation Person
    
    #pragma mark - 动态方法
    #pragma mark 带有参数的构造函数
    -(id)initWithName:(NSString *)name andAge:(int)age{
        if(self=[super init]){ //super代表父类
            self.name=name;
            self.age=age;
        }
        return self;
    }
    
    #pragma mark - 静态方法
    #pragma mark 通过静态方法返回一个对象
    +(id)personWithName:(NSString *)name andAge:(int)age{
        Person *p=[[Person alloc]initWithName:name andAge:age];
        return p;
    }
    
    #pragma mark - 重写方法
    #pragma mark 重写description
    -(NSString *)description{
        return [NSString stringWithFormat:@"{name:%@,age:%i}",self.name,self.age];
    }
    
    @end
    

    Student.h

    #import "Person.h"
    
    @interface Student : Person
    
    #pragma mark - 属性
    #pragma mark 分数
    @property (nonatomic,assign) float score;
    
    #pragma mark - 动态方法
    #pragma mark 带有参数的构造函数
    -(id)initWithName:(NSString *)name andAge:(int )age andScore:(float)score;
    
    #pragma mark - 静态方法
    #pragma mark 通过静态方法返回一个对象
    +(id)studentWithName:(NSString *)name andAge:(int )age andScore:(float)score;
    
    @end
    

    Student.m

    //
    //  Student.m
    //  ClassAndObject
    //
    //  Created by Kenshin Cui on 14-2-1.
    //  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
    //
    
    #import "Student.h"
    
    @implementation Student
    
    #pragma mark - 动态方法
    #pragma mark 带有参数的构造函数
    -(id)initWithName:(NSString *)name andAge:(int )age andScore:(float)score{
        if(self=[super initWithName:name andAge:age]){
            self.score=score;
        }
        return self;
    }
    
    #pragma mark - 静态方法
    #pragma mark 通过静态方法返回一个对象
    +(id)studentWithName:(NSString *)name andAge:(int)age andScore:(float)score{
        Student *s=[[Student alloc]initWithName:name andAge:age andScore:score];
        return s;
    }
    
    #pragma mark - 重写方法
    #pragma mark 重写description
    -(NSString *)description{
        return [NSString stringWithFormat:@"{name:%@,age:%i,nation:%@,scroe:%.2f}",self.name,self.age,self->_nation,self.score]; //注意这里访问了父类的属性和方法
    }
    
    @end
    

    main.m

    #import <Foundation/Foundation.h>
    #import "Person.h"
    #import "Student.h"
    
    int main(int argc, const char * argv[]) {
        
        Person *p=[Person personWithName:@"Kenshin" andAge:28];
        NSLog(@"p=%@",p);
        
        Student *s=[Student studentWithName:@"Kaoru" andAge:27 andScore:100];
        s.nation=@"henan";
        NSLog(@"s=%@",s);
        
        
        return 0;
    }
    

    iOS开发系列文章(https://www.cnblogs.com/kenshincui/p/3985090.html)

    相关文章

      网友评论

          本文标题:Objective-C类和对象

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