黑马程序员—OC学习笔记—@property和@synthesize的五种类型运用与归纳

———–Java培训、Android培训、IOS培训、.Net培训、期待与您交流!————
本节是个人学习过程中的笔记,供初学者一起学习,欢迎大家批评指正,留言参与讨论,谢谢。
本节内容,@property和@synthesize的五种类型运用与归纳,

总结了以下几点:
1、@synthesize出现时,服务对象(即为其提供自动方法)为最右侧的那个变量,或者就是唯一存在的那个变量。

2、在接口文件(.h)@interface之后{}大括号外面创建的变量,统一视为不可见,也就是private类型,包括在.m文件中创建的变量。

3、最简单地自动方式:@property type A; 如果 _A未声明,那么这一句话就干三件事,创建 _A,并提供服务。如果 _A已经声明,那么直接提供服务。

4、如果是用户手动+@property自动一起完成set和get,那么后者视为前者提供补充服务。

第三条和第四条,合在一起,就是一种用户行为优先与系统行为的原则。

代码如下:
main.m

//
//  main.m
//  Test作用域点语法和@property
//
//  Created by Mac on 15/4/2.
//  Copyright (c) 2015年 Mac. All rights reserved.
//

#import <Foundation/Foundation.h>

#import "Pupil.h"  // 调用孙子类的.h文件效率最高,虽然import不会重复包含,但是这样写更加简洁

//#import "Person.h"
//#import "Student.h"
//#import "Pupil.h"

// 测试点语法,并且stepinto内部,看清其跳转机制
void testDotGrammer()
{
    Person* p = [Person new];

    p.age = 10;

    int a = p.age;
    // 看p.age处于什么位置,对应的.语法,调用对应的set活着get方法。

    NSLog(@"p's age is %d",a);

    // 下面三行,跳转到@property double weight;这句话中,虽然进不去,但是效果是一样的。
    p.weight = 112.3;

    double w = p.weight;

    NSLog(@"p's weight is %.2f",w);
}

void testVariableArea()
{
    Student* s = [Student new];
    [s test];

    Pupil* p = [Pupil new];
    [p test];
}

void testPropertyAndSynthesize()
{
    Person* p = [Person new];

    // 第一种方式
    p.QQNum = 13324;
    NSLog(@"QQNum is %d",p.QQNum);

//    p._QQNum = 13324;
//    NSLog(@"QQNum is %d",p._QQNum);

//    p.Num = 13324;
//    NSLog(@"QQNum is %d",p.Num);

    // 第二种方式
    p.msnNum = 15524;
    NSLog(@"msnNum is %d",p.msnNum);

    // 第三种方式
    p.jdNum = 1888;
    NSLog(@"jdNum is %d",p.jdNum);

    // 第四种方式

    p.height = 1333;
    NSLog(@"height is %.2f",p.height);

    // 第五种方式
    p.ccNum = 123;
    NSLog(@"ccNum is %d",p.ccNum);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        testDotGrammer();
        testPropertyAndSynthesize();
        testVariableArea();
    }
    return 0;
}

Person.h

//
//  Person.h
//  Test作用域点语法和@property
//
//  Created by Mac on 15/4/2.
//  Copyright (c) 2015年 Mac. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    //@protected // 默认项,可以省略
    int _age;
    int _QQNum;
    double _weight;
    double _height;
    int ccNum;
    int _onlyForTest;

    @private
    int _idNum;
    char* _QQPsw;

    @public
    char* _name;
}

// 传统方式,自己敲冗余代码
- (void)setAge: (int)age;
- (int)age;

@property int idNum;

@property int onlyForTest;
// @property 和 @synthesize 一共好几种使用方式
// 第一种使用方式,最正规的方式
@property int QQNum;
// 下面都是第一种方式的延伸和探究
// @property int _QQNum; // 改成这个样子,也可以执行
// @property int Num; //


// 第二种方式,不创建成员变量,直接用一个新的变量来进行get、set简写
@property int msnNum;

// 第三种方式,不创建成员变量,只用property,不用synthesize
@property int jdNum;
// 创建 _jdNum(私有变量),声明并实现set,get

@property double weight;
// 这种情况类似,只是因为weight已经声明成为protected变量,所以不再是私有变量。

// 第四种方式 程序猿手动实现了set或者get方法,那么系统则优先考虑手动行为,不予创建,只是对其进行补足。这种用户和系统一起完成get、set的方式,不推荐使用,会有警告

//- (void)setHeight: (double)height;
- (double)height;
@property double height;

// 第五种方式,synthesize后面只有唯一一个变量,那么这个变量必须在大括号内声明,而且必须同名
@property int ccNum;

@end

Person.m

//
//  Person.m
//  Test作用域点语法和@property
//
//  Created by Mac on 15/4/2.
//  Copyright (c) 2015年 Mac. All rights reserved.
//

#import "Person.h"

@implementation Person

// 传统方式
- (void)setAge: (int)age
{
    _age = age;
}
- (int)age
{
    return _age;
}

// 第一种方式,最正规的方式
@synthesize QQNum = _QQNum;

// 下面都是第一种方式的延伸和探究
//@synthesize _QQNum = _QQNum;
//@synthesize Num = _QQNum;
// 这种方式也可以,说明,当synthesize存在的时候,以其后面最右边的那个变量为服务对象,只有一个变量的时候,就以那个变量为准。
// 但是这种方式可读性太差,也就失去了价值,只是为了说明synthesize做主的情况

// 第二种方式
@synthesize msnNum = msnNum;
// 这种方式创建并实现setget的变量,是一个私有变量,而是变量名称取决于最右侧。 也正是因为取决于实现部分的synthesize,所以才是私有

// 第三种方式 ,没有synthesize


// 第四种方式 程序猿手动和系统自动一起实现
//- (void)setHeight: (double)height
//{
//    _height = height;
//}

- (double)height
{
    return _height;
}

// 第五种方式
@synthesize ccNum;

// PS 测试,只有setget,没有声明也没有property去创建的情况
//- (void)setNewer: (int)newer
//{
//    _newer = newer;  // 这种方式,不行,_newer根本没法定义,所以不能出现,只有set、get,没有对应变量定义的情况
//}
//- (int)newer
//{
//    return _newer;
//}


@end

Student.h

//
//  Student.h
//  Test作用域点语法和@property
//
//  Created by Mac on 15/4/2.
//  Copyright (c) 2015年 Mac. All rights reserved.
//

#import "Person.h"

@interface Student : Person

- (void)test;

//@property int onlyForTest;

- (void)setOnlyForTest: (int)onlyForTest;
- (int)onlyForTest;
// 对于protected类型变量,子类可以重写么?答案是可以,private变量不行


//@property int idNum;
//- (void)setIdNum: (int)idNum;
//- (void)idNum;
// 以上不管哪种方式,都无法在子类中为父类未曾setget的private变量进行setget设定。
@end

Student.m

//
//  Student.m
//  Test作用域点语法和@property
//
//  Created by Mac on 15/4/2.
//  Copyright (c) 2015年 Mac. All rights reserved.
//

#import "Student.h"

@implementation Student

//@synthesize idNum = _idNum;
//- (void)setIdNum: (int)idNum
//{
//    self->_idNum = idNum;
//}
//
//- (void)idNum
//{
//    return _idNum;
//}

//@synthesize onlyForTest = _onlyForTest;

- (void)setOnlyForTest: (int)onlyForTest
{
    _onlyForTest = onlyForTest;
}

- (int)onlyForTest
{
    return 8985;
}

- (void)test
{
    _QQNum = 10;

    // msnNum = 10; // 由于是在大括号外创建的,所以为private类型
    //_jdNum = 18;
    _weight = 18; // 依然是原本的protected类型

    self -> _QQNum = 15;
    //self -> _id = 15;

    self.idNum = 12;
    NSLog(@"idNum is %d",self.idNum);

    self.onlyForTest = 999;
    NSLog(@"onlyForTest is %d",self.onlyForTest);

}
@end

Pupil.h

//
//  Pupil.h
//  Test作用域点语法和@property
//
//  Created by Mac on 15/4/2.
//  Copyright (c) 2015年 Mac. All rights reserved.
//

#import "Student.h"

@interface Pupil : Student
- (void)test;
@end

Pupil.m

//
//  Pupil.m
//  Test作用域点语法和@property
//
//  Created by Mac on 15/4/2.
//  Copyright (c) 2015年 Mac. All rights reserved.
//

#import "Pupil.h"

@implementation Pupil
- (void)test
{
    _age = 80;
    //_id = 33;
    // 因为是父类pravite,所以无法访问
    // 虽然无法直接访问,

    _QQNum = 666666;

    // msnNum = 10; // 由于是在大括号外创建的,所以为private类型
    //_jdNum = 18;
    _weight = 1866666; // 依然是原本的protected类型

    self -> _QQNum = 888888;
    //self -> _id = 15;



    //super -> _id = 32; //能否在子类方法中通过super去直接访问父类的private变量??

    // 如果子类全部继承父类的变量,那么在小学生这个子类里面,也应该有隐藏的成员变量,该如何访问
    //self -> _id = 123;

    // 不管成员变量是什么类型,在外部访问时候都是通过set和get来实现的,体现良好的封装性
}

@end

程序运行结果如下:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值