黑马程序员_OC学习之封装、继承、多态、组合

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! -----------------------


一、封装:给一个类的成员变量设置访问属性,隐藏内部实现,稳定外部接口。封装就是定义类的定义属性定义方法。

例如:

<span style="font-size:18px;">#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    @private
    int _age;
    @public
    int _id;
}

- (int)age;
- (void)setAge:(int)age;
@end

@implementation Person
- (int)age {
    return _age;
}
- (void)setAge:(int)age {
    if(age < 0) {
        age = 1;
    }
    _age = age;
}
@end

int main() {
    Person *p = [Person new];
//    p->_age = 10;   //这句是错误的,因为访问属性为私有,所以外部不可以访问
    [p setAge:10];  //应该这样设置
    NSLog(@"Age:%d",[p age]);
    
    p->_id = 10;  //这句正确,访问属性为public所以外部可以直接操作,但不建议这样使用
    
    NSLog(@"Age2:%d",p->_id);
    
    return 0;
}</span>
设计一个类时,成员变量一般不要设置成@public属性,如果想让外部更改成员变量值,应该公开设置器与访问器,这样体现了类的封装性。

----------------------------------------------------------------------------------------------------------------------------------------------------------

二、继承:子类可以调用父类的非私有成员变量和方法,并且子类在父类的基础上增加自己独有的属性或方法。

例如:

<span style="font-size:18px;">#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    @private
    int _age;
    @public
    int _id;
}

- (int)age;
- (void)setAge:(int)age;
@end

@implementation Person
- (int)age {
    return _age;
}
- (void)setAge:(int)age {
    if(age < 0) {
        age = 1;
    }
    _age = age;
}
@end

@interface Student : Person

@end

@implementation Student

@end

int main() {
    
    Student *s = [Student new];
    s->_id = 10;    //虽然子类没有任何定义,但是它继承了父类@public属性的成员变量
    NSLog(@"%d",s->_id);
    
    return 0;
}</span>
----------------------------------------------------------------------------------------------------------------------------------------------------------

三、多态:简单来说就是同一对象的不同形态。

例如:

<span style="font-size:18px;">#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    @private
    int _age;
    @public
    int _id;
}

- (int)age;
- (void)setAge:(int)age;
@end

@implementation Person
- (int)age {
    return _age;
}
- (void)setAge:(int)age {
    if(age < 0) {
        age = 1;
    }
    _age = age;
}
@end

@interface Student : Person

@end

@implementation Student

@end

int main() {
    
    Person *p = [Student new];  //学生同时也是人
    p->_id = 10;
    NSLog(@"%d",p->_id);
    
    return 0;
}</span>

一个学生,他同时有两种身份,一种为学生,第二,他也继承了人这个类,所以,他也是人(呵呵)。

多态的用处:如果两个类,一个学生,另一个老师,他们同时继承人这个类,这时我们设计一个函数,让学生跑或者让老师跑,这个函数的形参就可以是一个人的类,这样就体现了多态的好处。

----------------------------------------------------------------------------------------------------------------------------------------------------------

四、组合:继承的缺点是,增加了类与类之间的耦合性,如果我们更改了父类的方法或属性,那么会影响到他的所有子类。这时,我们可以使用组合的方式。

例如:

<span style="font-size:18px;">#import <Foundation/Foundation.h>
#import <math.h>

@interface Point2D : NSObject
{
    double _x;
    double _y;
}

- (void)setX:(double)x andY:(double)y;
- (double)x;
- (double)y;
- (double)distance:(Point2D *)p;
+ (double)distance:(Point2D *)p1 andP2:(Point2D *)p2;

@end

@implementation Point2D

- (void)setX:(double)x andY:(double)y {
    _x = x;
    _y = y;
}
- (double)x {
    return _x;
}
- (double)y {
    return _y;
}

- (double)distance:(Point2D *)p {
    
    return [Point2D distance:self andP2:p];
    
}

+ (double)distance:(Point2D *)p1 andP2:(Point2D *)p2 {
    //(x1 - x2平方+y1 - y2平方)  开根
    double d = sqrt(pow([p1 x] - [p2 x],2) + pow([p1 y] - [p2 y],2));
    
    return d;
    
}

@end

@interface Circle : NSObject

{
    double _radius;
    Point2D *_point;
}

- (void)setRadius:(double)radius;
- (double)radius;
- (void)setPoint:(Point2D *)point;
- (Point2D *)point;
- (bool)isOverlapped:(Circle *)c;
+ (bool)isOverlapped:(Circle *)c1 andCircle2:(Circle *)c2;
@end

@implementation Circle

- (void)setRadius:(double)radius {
    _radius = radius;
}
- (double)radius {
    return _radius;
}
- (bool)isOverlapped:(Circle *)c {
    return [Circle isOverlapped:self andCircle2:c];
}
+ (bool)isOverlapped:(Circle *)c1 andCircle2:(Circle *)c2 {
    //当两个圆心的距离小于两个圆之间的半径和表示重叠
    
    //两个圆心的距离
    double d = [Point2D distance:[c1 point] andP2:[c2 point]];
    
    //半径和
    double rD = [c1 radius] + [c2 radius];
    
    return d <rD;
}

- (void)setPoint:(Point2D *)point {
    
//    [_point setX:[point x] andY:[point y]];   //不可以这样写,因为这时,Circle中的point还是空
    
    _point = point;
}
- (Point2D *)point {
    return _point;
}

@end

int main() {
    Point2D *p1 = [Point2D new];
    Point2D *p2 = [Point2D new];
    
    [p1 setX:15 andY:15];
    [p2 setX:12 andY:19];
    
    Circle *c1 = [Circle new];
    Circle *c2 = [Circle new];
    
    [c1 setPoint:p1];
    [c2 setPoint:p2];
    
    [c1 setRadius:1];
    [c2 setRadius:2];

    if([Circle isOverlapped:c1 andCircle2:c2])
        NSLog(@"有重叠");
    else
        NSLog(@"无重叠");
    
    return 0;
}
</span>
Circle类中有一个Point2D类的对象作为他的成员变量,这种关系叫做组合。

注意:组合中初始化成员变量的问题:这个例子中:Circle类的setPoint方法不可以直接调用Point2D类的set方法,因为这时,Circle类中的Point2D对象还是空,所以我们要初始化其对象,就要新建一个Point2D对象,然后赋值给Circle类中的Point2D成员(虽然有点绕嘴,但不难理解)。





--------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值