【IOS 开发学习总结-OC-8.2】★★ objective-c面向对象之——类和对象(下)

知识点安插:如果访问权限允许,objective-c 允许直接通过对象来访问成员变量。语法格式:对象->成员变量名;

对象与指针

这里沿用上篇objective-c面向对象之——类和对象(上)的代码。
在 FKPersonTest.m中,有这样的代码:
FKPerson* person = [[FKPerson alloc] init];
这行代码产生了2个东西,一个是 person 变量,一个是 FKPerson 对象。这个FKPerson 对象被赋给person 变量。
从类的定义来看,FKPerson对象包含3个成员变量(2个暴露,1个隐藏),成员变量是需要内存来存储。因此,创建FKPerson对象时,必须有对应的内存来存储FKPerson对象的成员变量。FKPerson对象在内存里的存储示意图:
这里写图片描述
有图可以看出,FKPerson对象由多块内存组成,不同的内存块存储了不同成员变量。当把FKPerson对象赋值给FKPerson*变量时,其实是把FKPerson对象在内存中的首地址赋给了FKPerson*变量。FKPerson*类型的变量指向实际的对象。
本质上说,类是一种指针类型的变量。因此,程序定义的FKPerson*类型只是存放一个地址值,它被保存在该 main()) 函数的动态存储区,它指向实际的FKPerson对象,而真正的FKPerson对象存放在堆(heap) 内存里。如下示意图:
这里写图片描述
当一个对象被成功创建后,这个对象将保存在堆内存中,objective-c 不允许直接访问堆内存中的对象,只能通过该对象的指针变量来访问对象。就是说,所有的对象都只能通过指针变量来访问它们。堆内存里的对象可以有多个指针,即多个指针变量可以指向同一个变量。
如果堆内存里的对象没有任何变量指向该对象,那么程序将无法再访问该对象,如果程序员不释放该对象所占用的内存,就会造成内存泄露。

self 关键字

self 关键字总是指向调用该方法的对象。 它的最大作用是:让类中的一个方法访问该类的另一个方法或成员变量。

self 总是代表当前类的对象,当 self 出现在某个方法体中时,它所代表的对象是不确定的。但它的类型是确定的:它代表的对象只能是当前类的示例。当这个方法被调用时,它代表的对象才能确定下来:谁调用该方法,self 就代表谁。

示例代码:
头文件:FKDog.h

#import <Foundation/Foundation.h>

@interface FKDog : NSObject
// 定义一个jump方法
- (void) jump;
// 定义一个run方法,run方法需要借助jump方法
- (void) run;
@end

实现文件:FKDog.m

#import "FKDog.h"

@implementation FKDog
// 实现一个jump方法
- (void) jump
{
    NSLog(@"正在执行jump方法");
}
// 实现一个run方法,run方法需要借助jump方法
- (void) run
{
//  FKDog* d = [[FKDog alloc] init];
//  [d jump];
    [self jump];
    NSLog(@"正在执行run方法");
}
@end

FKDogTest.m文件:

#import <Foundation/Foundation.h>

#import "FKDog.h"

int main(int argc , char * argv[]) 
{
    @autoreleasepool{
        // 创建Dog对象
        FKDog* dog = [[FKDog alloc] init];
        // 调用Dog对象的run方法
        [dog run];
    }
}

用self区分重名的局部变量和成员变量

局部变量和成员变量重名的情况下,局部变量会隐藏成员变量。为了在方法中强行引用成员变量,可以使用 self 关键字进行区分。
示例代码:
FKWolf.h文件

#import <Foundation/Foundation.h>

@interface FKWolf : NSObject
{
    NSString* _name;
    int _age;
}
// 定义一个setName:ageAge方法
- (void) setName: (NSString*) _name andAge: (int) _age;
// 定义一个info方法
- (void) info;
@end

FKWolf.m 文件

#import "FKWolf.h"

@implementation FKWolf
// 定义一个setName:ageAge方法
- (void) setName: (NSString*) _name andAge: (int) _age
{
    // 当局部变量隐藏成员变量时,
    // 可用self代表调用该方法的对象,这样即可为调用该方法的成员变量赋值了。
    self->_name = _name;
    self->_age = _age;
}
// 定义一个info方法
- (void) info
{
    NSLog(@"我的名字是%@, 年龄是%d岁" , _name , _age);
}
@end

int main(int argc , char * argv[]) 
{
    @autoreleasepool{
        FKWolf* w = [[FKWolf alloc] init];
        [w setName: @"灰太狼" andAge:8];
        [w info];
    }
}

把 self 当成普通方法的返回值

当 self 作为对象的默认引用使用时,程序可以像访问普通指针变量一样访问这个 self引用,甚至可以把 self 当成普通方法的返回值。
示例程序:
ReturnSel.m文件

#import <Foundation/Foundation.h>

@interface ReturnSelf : NSObject
{
    @public
    int _age;
}
- (ReturnSelf*) grow;
@end

@implementation ReturnSelf
- (ReturnSelf*) grow
{
    _age++;
    // return self,返回调用该方法的对象
    return self;
}
@end

int main(int argc , char * argv[])
{
    @autoreleasepool{
        ReturnSelf* rt = [[ReturnSelf alloc] init];
        //可以连续调用同一个方法
        [[[rt grow] grow] grow];
        NSLog(@"rt的_age成员变量的值是:%d" , rt->_age);
    }
}

说明:使用 self 作为方法的返回值可以使代码更加简洁,但可能造成实际意义的模糊。

id 类型

id 类型可以代表所有对象的类型。任意类的对象都可赋值给 id 类型的变量。
通过 id 类型的变量来调用方法时,objective-c 将会执行动态绑定。动态绑定:objective-c 将会跟踪对象所属的类,会在运行时判断该对象所属的类,并在运行时确定需要动态调用的方法,而不是在编译时确定要调用的方法。
示例程序:

#import <Foundation/Foundation.h>

#import "FKPerson.h"

int main(int argc , char * argv[]) 
{
    @autoreleasepool{
        // 定义id类型的变量,并将FKPerson对象赋给该变量
        id p = [[FKPerson alloc] init];
        // 使用p变量来调用say:方法。
        // 程序将在运行时执行动态绑定,因此实际执行FKPerson对象的say:方法
        [p say: @"你好,疯狂iOS讲义"];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值