黑马程序员----objective-C 核心语法

来源:互联网 发布:多用户 分销 源码 编辑:程序博客网 时间:2024/05/21 09:52

-------android培训、java培训、IOS培训、期待与您交流!-------

点语法

Person *p = [Person new];

p.age = 10;/* 点语法的本质还是方法调用,当使用点语法,编译器遇到了自动展开[p setAge:10];

而且它不是访问成员变量age(成员变量为_age),p->_age是OC里面直接访问成员变量的唯一方式

 

int a = p.age// [p age] age的get方法

判断是set还是get方法:有没有赋值,赋值是set方法

对p.age打断点测试,用左下第四个按钮 setp into跳转代码到set方法,从而验证了赋值点语法的本质是set方法。

 

- (void)setAge:(int)age

{

    //_age = age;

   

    NSLog(@"setAge:");

   

    // 会引发死循环

    //self.age = age; // [self setAge:age];

}

 

- (int)age

{

    NSLog(@"age");

    return _age;

    // 会引发死循环

    //return self.age;  //[self age];

}

成员变量的作用域

@interface Person : NSObject

{

@public

//*任何地方都可以直接访问对象成员变量(直接通过成员变量名),当然首先得有对象*/

 

@private

// 只能在当前类的对象方法中直接访问。子类虽然不能访问,但是仍然是拥有这个成员变量的。

 

@protected// 能在当前类和子类的对象方法中直接访问(不写默认就是@protected)

 

@package : 只要处在同一个框架中,就能直接访问对象的成员变量。

 

}

 

#import <Foundatition/Foundatition.h>

#import "Person.h"

int main()

{

    Person *p = [Person new];

    p->_age = 100;

    p->_height = 12;//这是private的会报错的

}

 

如果想在子类访问私有成员变量调用方法

@implementation Student

{

    int _aa;//也可以的。但是它默认不是protected而是私有private

    //@implementation 中不能定义和@interface中同名的成员变量。

}

-(void)study

{

    [self setHeight:15];

    int h = [self height];

    -weight = 100;

}

 

关键字@property

@property 关键字可以自动生成某个成员变量的setter和getter方法的声明:

@property int age;

编译时遇到这一行,则自动扩展成下面两句:

- (void)setAge:(int)age;

- (int)age;

 

@property int _age;

//最好不要写_age,因为这样生成的不是标准的setget方法

@property int _age;

p.age = 10;//报错,生成的是下划线(void)setAge(int)_age;

 

@synthesize关键字

@synthesize关键字帮助生成成员变量的setter和getter方法的实现

#import <Foundatation/Foundatition.h>

@interface Person : NSObject

{

    int age;

    int _age;

}

@property int age;

- (void) test;

@end

 

@implementation

//自动生成age的setter和getter,并且访问_age这个成员变量

@synthsize age = _age, name = _name//还可以两个在一起;

- (void) test

{

    NSLog(@"age=%d, _age=%d",age, _age);

}

@end

int main()

{

    Person *p = [Person new];

    [p setAge:10];

    [p test];

}

 

需要注意的地方

 

#import <Foundation/Foundation.h>

@interface Car : NSObject

{

   /*@protected

   int _age;

   如果不想自动生成@private就在这里添加个@protected

    */

    int _wheels;

    int _speed;

}

 

//很少有写在一起的@property int wheels,speed;//都是int型

@property int wheels;

@property int speed;

 

@end

 

@implementation

 

//@synthsize wheels = _wheels,speed = _speed;

//会访问下划线_speed这个成员变量,如果不存在,就会自动生成@private类型成员变量

@synthsize wheels = _wheels;

@synthsize speed = _speed;

 

@synthsize age;

//如果不写等号后面的,就是访问同名成员变量也就是age而不是_age;

//如果没有age,就会自动生成@private类型的age变量

 

- (void)test

{

    NSLog(@"速度=%d", _speed);

}

@end

 

int main()

{

    Car *c = [Car new];

    c.speed = 100;

    [c test];

    NSLog(@"%d", c.speed);

}

@property只能写在@interface  @end中,@synthesize只能写在@implementation   @end中,自从xcode 4.4后,@property就独揽了@property和@synthesize的功能.

原则:get和set方法同变量一样,如果自己定义了,那么就使用已经定义的,如果没有定义,那么就自动生成一个。

手动实现:

1)如果手动实现了set方法,那么编译器就只生成get方法和成员变量;

2)如果手动实现了get方法,那么编译器就只生成set方法和成员变量;

3)如果set和get方法都是手动实现的,那么编译器将不会生成成员变量。

 

Id类型

 

 

 #import <Foundatation/Foundatition.h>

@interface Person : NSObject

{

    int _age; 

}

@property int age;

@property id obj;

 

void test(id d)

{

    任何对象都能传递进来。

}

 

@end

 

@implementation

@end

int main ()

{

    Person *p = [Person new];

   

   //id  == NSObject *

    id d = [Person new];//万能指针,能指向\操作任何OC对象

    [d setAge:10];

 

    [d setObj:@"daf4568asdf"];//任意对象都可以

    NSLog(@"%d",[d age]);

}

id 类型的定义

Typedef struct objc object{

Class isa;

} *id;

注意:在id的定义中,已经包好了*号。Id指针只能指向os的对象。

只要求掌握两点就完事了: 1. id  == NSObject *

2. id 后面不要加 *

Person.m

 

#import "Person.h"

@implementation

 

//重写-init方法

- (id)init

{

   //1.一定要调用回super的init方法:初始化父类中声明的一些成员变量和其他属性

    self = [super init];//当前对象 self

   

    //2,如果对象初始化成功,才有必要进行接下来的初始化

    if (self != nil)

    {//初始化成功

       _age = 10;

    }

   

   //3,返回一个已经初始化完毕的对象

    return self;

}

 

//简写版

 

- (id)init

{

    if ( self == [super init])

    {

       _age = 10;

    }

    return self;

}

@end

Student.m

 

#import "Student.h"

- (id)init

{

    if( self = [super alloc])//不要追究self后面的等号,固定写法

    {  

       //_age = 10这句话是不必要而且错的,super父类-init里面有,就不用再赋值,而且因为_age是私有的,超过了成员变量的作用域

       _no = 1;

    }

    return self; 

}

 main.m

 

#import "Person.h"

 

//构造方法 :用来初始化对象的方法,是个对象方法,-开头

//重写构造方法的目的:为了让对象创建出来,成员变量有个固定值

/*

重写构造方法的注意点

1.先调用父类的构造方法[super init]

2在进行子类内部变量的初始化。

 

*/

int main()

{

    Person *p = [Person new];

    /*new方法内部调用两个方法:完整创建一个可用对象

   1,分配存储空间 + alloc方法

   2,初始化   -init方法

    */

    //1.调用+alloc分配存储空间

    Person *p1 = [Person alloc];//Return a new instance of the receiving class.

   

    //2,调用-init进行初始化

    Person *p2 = [p1 init];

   

   //整合,以后不要写new,写init

    Person *p3 = [[Person alloc] init];

    p3.age = 10;//每次保证创建出的对象成员变量为10

 

    //每个Person对象创建出来,他的_age是10.

    Person *p4 = [[Person alloc] init];

 

    Student *stu =[[Student alloc] init];

    NSLog(@"----");

 

    return 0;

}

 

三个构造方法

Student

-(id)init

{

    if(self = [super init])

    {

       _no = 1;

    }

    return self;

 

}

Person

-(id)init

{

    if(self = [super init])

    {

       _age = 10;

    }

    return self;

 

}

NSObject

-(id)init

{

    isa = [self class];

    return self;

}

自定义构造方法

@interface Person : NSObject

@property NSString *_name;

@property int _age;

 

/*自定义构造方法的规范

1.一定是对象方法,以-号开头

2.返回值一般是id类型

3,方法名一般以initWith开头

*/

 

- (id)initWithName:(NSString *)name;

 

- (id)initWithName:(NSString *)name andAge:(int)age;

@end

 

@implementation Person

 

- (id)initWithName:(NSString *)name

{

    if ( self = [super init])

    {

       _name = name;

    }

    return self;

}

- (id)initWithAge:(int)age

{

    if(self = [super init])

    {

       _age = age;  

    }

}

 

- (id)initWithName:(NSString *)name andAge:(int)age

{

    if (self = [super init])

    {

       _name = name;

       _age = age;

    }

    return self;

}

@end

 

int main()

{

    Person *p = [[Person alloc] initWithName:@"Rose"];

    //等价于Person *p = [[Person alloc] init];p.name =@"Rose";

 

    Person *p2 = [[Person alloc] initWithAge:20];

   

    Person *p3 = [[Person alloc] initWithName:@"jack" andAge:27];

}

 

#import "Person.h"

 

@interface Student : Person

@property int no;

 

- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no;

@end

 

@implementation Student

 

//父类的属性交给父类方法去处理,子类的方法处理子类自己的属性

- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no

{

    /*将name,age传递到父类方法中进行初始化。自己管自己的no就行了

   好处:一旦父类改动name父类成员变量的名字,不会对这种方法产生影响,因为它对父类的成员变量已经交由父类自己处理。

    */

 

    if ( self = [super initWithName:name andAge:age])

//注意name,age前面无类型。

    {

       _no = no;

    }

   

    /*if (self = [super init])

    {

       _no = no;

       self.name = name;

       self.age = age;

 

       //_name = name;父类变量私有不能在这里写

    //[self setName:name];首先调用本类里面的setName没有,再找super的。

    //[self setAge:age];

    }*/

    return self;

}

 

@end

 

int main()

{

    Student *s = [[Student alloc] initWithName:@"jim" andAge:23 andNo:3];

}



0 0