OC_02

来源:互联网 发布:数字电子网络配线架 编辑:程序博客网 时间:2024/06/06 03:44
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
#import "Teacher.h"
#import "NewStudent.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
       
        /*
         OC中的方法
         设置器与访问器
         便利初始化函数  以及  便利构造器
         属性
         */
        //OC中的方法
        //实例方法
        //Person *a = [Person new];
        Person *a = [[Person alloc] init];
        
        //如何调用使用实例方法(通过对象调用)
        [a sayHello];
        [a sayHelloName:@"Yong" andAge:23];
        
        //如何调用类方法(通过类名调用)
        [Person sayHi];
        
        [Person hiGuys];
        
        //设置器与访问器
        //我们知道,一个类的实例变量如果是被@protected或者@private 所修饰,那么我们将不能对该成员变量进行赋值.这满足了我们希望的封装和安全.但是为了交换信息,我们希望使用@pulice类型.似乎这两者的矛盾不可调节.这个时候我们就可以使用设置器与访问器来解决这个问题
        
        Student *stu = [[Student alloc] init];
        [stu setName:@"Yong"];
        NSLog(@"%@",[stu name]);
        
        [stu setAge:23];
        NSLog(@"%ld",[stu age]);
        
        //便利初始化函数 以及 便利构造器
        
        Teacher *teacher = [[Teacher alloc] init];
        
        [teacher sayWord];
   
        
        Teacher *teacher1 = [[Teacher alloc] init];
        [teacher1 sayWord];
        
        Teacher *teacher2 = [[Teacher alloc] initWithName:@"Chen" andAge:23];
        [teacher2 sayWord];
        
        Teacher *teacher3 = [Teacher teacherWithName:@"ChenYong" andAge:24];
        [teacher3 sayWord];
        
        //属性
        //在这里,我们可以使用点语法来访问属性,点语法被称为"语法糖果",它只是为了方便我们书写而发明的,它的本质还是getter和setter语法
        
        NewStudent *newStudent = [[NewStudent alloc] init];
//        [newStudent setName:<#(NSString *)#>]
        newStudent.name = @"Yong";//(点语法赋值)
        newStudent.age = 23;
        newStudent.homeAddress = @"GZ";
        
        NewStudent *newstudent = [[NewStudent alloc]initWithName:@"Yong" andAge:23 andHomeAddresss:@"GZ"];
        
        
    }
    return 0;

}


在Teacher.h文件里

#import <Foundation/Foundation.h>

@interface Teacher : NSObject
{
    NSString *_name;
    NSInteger _age;
}

-(void)sayWord;

//便利初始化函数(实例方法)
//注意命名规范:init开头
-(id)initWithName:(NSString *)name
           andAge:(NSInteger)age;

/*
 便利构造器(类方法)
 便利构造器只不过是把对象分配内存 和 便利初始化函数 初始化对象的代码封装起来,让用户使用起来更加方便
 注意命名规范: className 开头,例如teacher
*/

+(id)teacherWithName:(NSString *)name
              andAge:(NSInteger)age;

@end

在Teacher.m文件里

@implementation Teacher


/*
 id:返回的类型是id数据类型,它是动态数据类型,它可以指向任何的对象,而不关系具体类型,在运行时检查其具体类型,可以对其发送任何(存在的)消息
 
 self:指向当前对象的指针
 
 super:指向父类对象的指针,子类使用super发送消息时,实际上就是告诉子类调用我们父类的方法,如果父类没有定义该方法,则会继续在继承链上寻找,直到寻找到位置,如果找到NSObject位置依然没找到,就会报错
 
 其中(self = [super init]),此处[super init]任然返回子类对象,此处的目的是为了初始化父类的实例变量,如果返回nil,表面父类没有alloc成功,即不能再alloc子类对象
 
 */

-(id)init //重写init
{
    if (self = [super init])
    {
        _name = @"Yong";
        _age = 23;
    }
    return self;
}
//便利初始化
-(id)initWithName:(NSString *)name
           andAge:(NSInteger)age
{
    if (self = [super init])
     {
         _name = name;
         _age = age;
    }
    return self;
}

//便利构造器
+(id)teacherWithName:(NSString *)name
              andAge:(NSInteger)age
{
    Teacher *teacher = [[Teacher alloc] initWithName:name andAge:age];
    return teacher;
}


-(void)sayWord
{
    NSLog(@"Teacher who names %@,%ld years old,say hello guys",_name,_age);
}



@end

在NewStudent.h文件里

#import <Foundation/Foundation.h>

@interface NewStudent : NSObject
//{
//    NSString *_homeAddress;
//    NSString *_name;
//    NSInteger _age;
//}
//对于homeAddress来说
//-(void)setHomeAddress:(NSString *)homeAddress;
//
//-(NSString *)homeAddress;

//属性的声明
//@property NSString *homeAddress;  //相当于声明了设置器和访问器

//-(void)setHomeAddress:(NSString *)homeAddress;
//-(NSString *)homeAddress;

//完整的属性声明
/*
 @property(readwrite,nonatomic,strong)NSString *homeAddress;
 
 访问读写(readwrite),原子性(nonatomic),内存管理(strong)
 访问读写:readwrite   指明属性是可读写的,这是默认值,因此可以省略.
         readonly    指明属性是只读的,系统只会产生getter(访问器)方法,而不会产生setter(设置器)方法
 可读写性确定属性是否有setter方法,他们是互斥的
 对于只读写的属性,如果试图通过点语法给其赋值,会编译错误
 
 原子性:atomic      原子性操作,这是默认的
       nonatomic   非原子性操作,一般就使用它,但是它没有办法保证在多线程环境下不出错
 
 内存管理:retain    会通过retain来持有目标对象,之前的对象会接收到释放的消息
         copy      会通过copy复制对象,之前的对象会接收到释放的消息
         assign    表面采用简单的赋值方式,这是默认的方式
 
         strong    表示强引用关系,即拥有目标对象的所有权
         weak      表示弱引用关系,不拥有目标对象的所有权,但目标对象被销毁,属性值会自动设置为nil
 
 strong  相当于 retain 或者 copy,对象要用retain,copy,strong来描述
 
 weak 相当于 assign ,基本数据类型要用assign 来描述
 weak 与 assign 的区别
 weak:可以描述对象
 assign:不可以描述对象
 */

//@property 的设置器声明,这里没有下划线
//注意:直接操作实例变量而没有进行retain或copy操作,可能会引起内存泄露或者引用技术错误
@property(readwrite,nonatomic,strong)NSString *homeAddress;

@property(readwrite,nonatomic,strong)NSString *name;

@property(readwrite,nonatomic,assign)NSInteger age;

-(id)initWithName:(NSString *)name
           andAge:(NSInteger)age
  andHomeAddresss:(NSString *)homeAddress;


@end

在NewStudent.m文件里

@implementation NewStudent

//属性的实现(相当于设置器和访问器的实现),这句话也可以省略
//@synthesize homeAddress = _homeAddress;

/*
 注意:如果我们把@synthesize注释掉了,这时候系统会为我们自动生成以下划线开头的变量.所以在类实现文件的内部,我们需要使用_name 来代替name,用_age 来代替age.
 */

//-(void)setHomeAddress:(NSString *)homeAddress
//{
//    _homeAddress = homeAddress;
//}
//
//-(NSString *)homeAddress
//{
//    return _homeAddress;
//}

-(id)initWithName:(NSString *)name
           andAge:(NSInteger)age
  andHomeAddresss:(NSString *)homeAddress
{
    if (self = [super init])
    {
//        _name = name;
//        _age = age;
//        _homeAddress = homeAddress;
        
        //对于只读readonly来讲,不能使用 self.age ,因为它没有设置器
        //对于可读可写通常使用 self.name = name 的这种方式
        self.name = name;
        
    }
    return self;
}



@end

在Student.h文件里

#import <Foundation/Foundation.h>

@interface Student : NSObject
{
    NSString *_name;
    NSString *_hobby;
    NSInteger _age;
}

//设置器(setter)和访问器(getter)
//name的设置器
-(void)setName:(NSString *)name ;

-(void)setAge:(NSInteger)age;

//name的访问器
-(NSString *)name ;

-(NSInteger)age;

@end

在Student.m文件里

@implementation Student

//name的设置器
-(void)setName:(NSString *)name
{
    _name = name;
}

//对于age属性来说,做正确性检验
-(void)setAge:(NSInteger)age
{
    {
        //    _age = age;
        
        if (age < 18)
        {
            _age = 18 ;
        }
        else
        {
            _age = age;
        }
    }
}

//name的访问器
-(NSString *)name
{
    return _name;
}

-(NSInteger)age
{
    return _age;
}
/*
 设置器与访问器的作用
 1.隐藏了实例变量
 2.控制实例变量的读写
 3.做正确性的校验
 
 对于设置器与访问器来说,其命名规则:
   1.设置器:-(void) set首字母大写的实例变量:(实例变量的返回值类型)去掉下划线的实例变量名
   2.访问器:-(实例变量返回值类型) 去掉下划线的实例变量名
 
 注意:
    对于类的名称,其首字母要大写
    对于变量,其首字母小写
    遵循骆驼峰命名规则
 
 
 有了setter 和 getter , 我们就可以把变量都定义@protected 或者 @private类型,尽量不要使用@public类型,它的好处如下:
 1.在setter中加入合法性检查,例如判断年龄要大于0
 2.更新被设置变量相关的其他变量的值,比如年龄与年份的关系
 3.可以在debug中,在setter中追踪log
 4.在多线程中,如果要保护对象的并发访问,侧必须在getter/setter中加入同步锁
 
 缺点:手动编写麻烦
 
 */


@end

在Person.h文件里

@interface Person : NSObject
{  
    NSString *_name;
    NSInteger _age;
    NSString *_hobby;
}

/*
   OC中的方法
   方法:
      是类的功能代码,在(.h)文件中声明,在(.m)文件中实现.
   语法:
      -|+ (返回类型) 方法名:参数列表
      {
         //方法体
 }
 
 减号(-)表示实例方法,加号(+)表示类方法
 */

-(void)sayHello;
//无返回值有参数实例方法
-(void)sayHelloName:(NSString *)name
             andAge:(NSInteger)age;
//类方法
/*
 注意:
  1.类方法可以调用类方法
  2.类方法不可以调用实例方法,但是类方法可以通过创建实例对象来访问实例方法
  3.类方法不可以使用实例变量.类方法可以使用self,因为self不是实例变量
  4.类方法作为消息,可以被发送到类里面去,不能发送到对象里面去
 */
+(void)sayHi;

+(void)hiGuys;
@end

在Person.m文件里

@implementation Person

//实例方法
-(void)sayHello
{
    NSLog(@"sayHello!");
}

-(void)sayHelloName:(NSString *)name andAge:(NSInteger)age
{
    
    NSLog(@"Hello guys!My name is %@,I am %ld years old!",name,age);
}

//类方法
+(void)sayHi
{
    NSLog(@"sayHi!");
}

+(void)hiGuys
{
    //1.类方法可以调用类方法
    //self 是什么?  self代表当前对象的指针
    [self sayHi];
    
    //2.类方法不可调用实例方法,但是类方法可以通过创建实例对象来访问实例方法
    Person *p = [[Person alloc] init];
    [p sayHello];
    
    //3.类方法不可以使用实例变量.类方法可以使用self,因为self不是实例变量
//    NSLog(@"hi,My is %@,age is %ld,hobby is %@",_name,_age,_hobby);
    
    
    
}
@end

0 0