黑马程序员------OC @property 关键字及构造方法的使用

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

一  、@property 关键字的使用

    1.点语法 编译器的特性,编译器帮我们做代码替换

      在掉用时,set方法[p setAge:19];   [p setName:@"zlz"];

      点语法  对象.属性名

     注意此时,(对象.属性名)并不是直接访问实例变量,而是xcode看到点语法(p.age)后,会自动替我们生成[p setAge 18]

        p.age --替换-->[p setAge: 18]

     

     int a =[p age];//调用get方法  NSString *s = [p name]

     注意: 此处p.age是出现在等号右侧

     实际上,当xcode 看到 p.age 出现在等号的右侧后,会帮我么把p.age --替换成-->[p age];

      int a = p.ag //调用get方法

    强调:p.age到底是替换成get 还是set方法,一般取决于p.age 是出现在等号左侧还是右侧(是设置值,还是取值)

     注意:点语法的本质是转换成相应的getset方法,如果没有set get方法 ,则不能使用点语法。

   2.@property关键字的使用

       1.@property的介绍

         @property 是编译指令

         在4.4之前  @property 告诉编译器 声明属性的访问器(getter setter)方法 4.4 之后有增强功能

       2.@property的使用

         @property的用法 @property 类型名 实例变量名(方法名)

         @property int age; 相当于进行了agesetget方法的声明

           - (void)setAge:(int)age;

           - (void)age;

   3.@synthesize关键字

      1.@synthesize 用法

         @property int age@synthesize age ;表示生成.h变量的agesetset方法的实现

        注意:如果@synthesize 变量名要先在.h中声明

        @synthesize age 帮我们生成变量age

          - (void)setAge:(int)age{

            self ->age  =age;

 

        }

        - (int)age{

            return age;

        }

 

      2.@synthsize指定实例变量赋值

          如果两个实例变量的类型一致 可以 @synthesize ageweight

            指定操作实例变量的@synthesize 方法名 实例变量名

            当指定实例变量以后,此时再不会操作默认的实例变量

            @synthesize age = _age, weight =_weight;

            @synthesize name =_name;

      3.property 曾强使用

          xcode 4.4 之后 只使用@property 可以自动生成和实现settergetter方法。

               @property int age; @orperty NSString* name 

             这里生成的都是 _age 和 _name;和自己手动设置的get set是一致的。。

               操作的是下划线的实例变量 ,如果我们当前类并没有下划实例变量,则系统会自动帮我们生成。

                    生成 int _age; NSString *_name; 实例是私有的。不能被子类看到。

    4.@porperty 下重写getset方法

            为了过滤条件。get方法和set方法在.m中可以自己动手实现,

             getset方法不能同时手动实现。

        - (void)setAge{

            if(age>0){   //年龄是整数才算合理。 这里对set重写。

                _age =age;

            }else{

                _age = 0;

            }

 

        }

 

二、动态类型和静态类型

     多态:允许不同的类定义相同的方法。

     动态类型: 程序直到执行时才能确定所属的类

     静态类型:将一个变量定义为特定的对象时,是静态的。

   

    1.id类型

            Animal *ani=[Animal new];

            [ani run];动物在跑

          Animal *an2 = [Dog new];

                [an2 run];狗在跑

 

        NSObject *obj = [Anmal new];

         [(Animal*)obj run];//访问子类特有的方法 强制转换

        obj = [Dog new];

        [(Dog*)obj  run];

       NSObject是所有类的基类。obj可以指向任何子类

     注意 id 的使用

            id obj2;          NSObject id都可以指向对象

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

            [obj2 run];            id不需要强制类型转换,id 可以直接使用

            obj2 =dog;              编译器看到id以后,认为是动态类型,不检查类型。

            [obj2 run]

    2.动态类型检测

        1)判断类型

          -(BOOL)isKindOfClass:classObj   

           判断实例对象是否是这个类或者这个子类的实例对象  格式[对象  isKindOfClass: 类对象]

            BOOL isInstance = [ani isKindOfClass:[Animal class]]; ani Animal的实例

        2)-(BOOL)isMemberOfClassclassObj 判断对象是否是指定类的实例对象

             格式 [对象 isMemberOfClass:对象]

        3)判断是否是指定类的子类(类和类之间的关系)

                格式 :类A isSubclassOfClass:类B

        +(BOOL) isSub = [ Dog isSubclassOfClass:[Animal class];

        4)

      判断对象能否响应指定的方法

         - (BOOL)respondsToSelector:selecctor 判断实例是否有这样方法能响应run方法

             判断,如果 ani 能够调用 eat 方法,然后就调用

          SEL s1 =@selector(eat);//eat包装成SEL类型

        BOOL isResspond =[ani respondsToSelector :s1];

      判断类中有没有调用指定方法

            EL s1 =@selector(eat);

            is Respond =[Dog instancesRespondToSelector:s1];

        

      响应方法

        Animal*ani =[Dog new];

         SEL s1 =@selector(eat);

        if([ani respondsToSelector:s1]){

                [ani performSelector];//作用,响应方法

        }else{

 

         通过performSelector: withObject :响应有参的方法

         SEL s2 = @selector(eat);

         [ani performSelector:s2 withObject:@"lzl"]

三、构造方法 

     oc中的构造方法:给对象进行初始化的方法

     oc中给对象初始化的方法是:init 该方法是一个对象方法 ,返回的时一个对象(调用init的对象)

     oc中的构造方法,主要学习 如何重写构造方法,让对象创建成功后,就有初始值。

        [[Person alloc] init] 等价于 [Person new]

     1.init 方法就是一个构造方法,是用来初始化对象的方法,注意这是一个对象方法,以减号开头,初始化完毕,所有成员变量的值都为0.

     2.alloc  向某个类发送alloc消息 ,为该类分配内存,以存放该类的全部实例变量,还将这块区域全部初始化为0

    

     3.重写构造方法 

         需求Person 对象创建完成以后 ,年龄默认是10

        //通过修改默认的构造方法来实现

        

        @importementation Person

        //当子类把父类的init覆盖了,这是默认的先执行子类的

        - (instancetype)init{

              //先让父类把父类原来做的事情完成 判断父类是否初始化成功

        if(self = [super init]){

                _age =10;//此处写子类的初始化类容 。给年龄设置默认值为 10岁。

        }

 

            return self/代指的是方法的调用者

         }

#import 

@interface Gun : NSObject
@property int bulletCount;
- (void)shoot;
@end

#import "Gun.h"

@implementation Gun
- (instancetype) init {
    if (self =[super init]) {
        _bulletCount =3;   //让每把枪都有3颗子弹
    }
    return self;
}

- (void)shoot{
    _bulletCount--;
    if(_bulletCount >0){
        NSLog(@"正在射击。。。当前子弹还有%d",_bulletCount);
    }else{
        NSLog(@"每子弹了请换子弹");
    }
}
@end
#import "Gun.h"

@interface Solider : Gun
{
    Gun* _gun; 
}
-(void)fire;
-(instancetype)init;
@end


#import "Solider.h"

@implementation Solider

-(void)fire{
    [_gun shoot];
  
}
-(instancetype)init{
   //重写init
if (self =[super init]) {
        Gun*  gun = [Gun new]; //创建一个枪对象

        _gun= gun; 
    }
    return self;
}
@end
#import 
#import "Gun.h"
#import "Solider.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
       //创建20个士兵
        for(int i =0;i<20;i++){
            
            Solider *s1 =[[Solider alloc] init];
            
            [s1 fire];
        }

    }
    return 0;
}


 

4.自定义构造方法

        一定是对象方法,以减号开头

        返回值一般是id类型 

        方法名 一般以initWith开头。

#import 

@interface Person : NSObject
@property NSString * name ;
@property int age;
- (instancetype)initWith:(NSString*)name andAge:(int)age;
@end
#import "Person.h"

@implementation Person
- (instancetype)initWith:(NSString*)name andAge:(int)age
{    
 //重写Person的init
    if (self = [super init]){
        _name = name;
        _age  = age;
    }
    return self ;
}


@end

#import "Person.h"

@interface Student : Person
@property int sno;
- (instancetype)initWith:(NSString*)name andAge:(int)age andSno: (int)sno;
@end
#import "Student.h"

@implementation Student
- (instancetype)initWith:(NSString*)name andAge:(int)age andSno: (int)sno{
    //继承父类的init方法、、
    if (self =[super initWith:name andAge:(int)age]) {
        _sno = sno; //给自己的赋值 学号
    }
    return self;

}
@end
//Person 类创建成功,给人起一个名字 让后再对年龄进行初始化
// 创建一个学生类 要求 有学号

#import 
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //创建对象 同时指定名字和 年龄
        Person *p =[[Person alloc] initWith:@"lzl" andAge:18];
      
        NSLog(@"姓名:%@  年龄%d",p.name,p.age);
        
    
        Student * stu =  [[Student alloc] initWith:@"zhangsanf" andAge:28 andSno:1];
        NSLog(@"姓名:%@  年龄%d  学号%d",stu.name,stu.age,stu.sno);

    
    }
        return 0;
}


 

你可能感兴趣的:(黑马程序员------OC @property 关键字及构造方法的使用)