黑马程序员——OC基础——类的三大特性(2)

-----------android培训java培训、java学习型技术博客、期待与您交流!------------

这次我们学习类的三大特性中的继承和多态。

继承的概念: 继承是从已有的类中派生出另一个类,这个类可以继承已有的类的属性和方法,并能够进行扩展。比如说我们新建了一个Person类,那么我们可以在这个类上派生出一个新的类Student类,Student类可以拥有Person类的全部属性和方法并能够进行扩展。

下面我们先建立一个Person类。

@interface Person : NSObject
{
    int _age;
    NSString *_name;
}
// name的set和get方法
- (void) setName:(NSString *)name;
- (NSString *)name;

// age的set和get方法
- (void) setAge:(int)age;
- (int) age;

// 定义一个对象方法test
- (void) eat;
@end

// 类的实现
@implementation Person
- (void) setName:(NSString *)name;
{
    _name = name;
}
- (NSString *)name
{
    return _name;
}

- (void) setAge:(int)age
{
    _age = age;
}
- (int) age
{
    return _age;
}

- (void) eat
{
    NSLog(@"%@在吃饭",_name);
}
@end


 
 
 
上面的代码就是我们新建的Person类的声明和实现。其实Person也是继承了一个类NSObject的,这个类是所有的OC类都必须继承的,它是所有类的父类。类是不允许多继承的,也就是A既继承了B、也继承了C,这是不允许的。 

类的继承关系只需要写在类的声明上,格式是在类名后面加上冒号,冒号后面写上父类的类名就可以了。

下面我们再新建一个Student类并让Student继承Person类:

@interface Student : Person
{
    //这里我们定义了一个Student特有的属性_no
    int _no;
}

// _no的set和get方法
- (void) setNo:(int)no;
- (int) no;
@end
@implementation Student
- (void) setNo:(int)no
{
    _no = no;
}
- (int) no
{
    return _no;
}
@end

上面我们定义了一个Student类并继承了Person类。可以看出我们并没有去定义Person类已有的属性,而只是定义了一个Student类特有的属性_no,那么我们怎么调用父类的方法和属性呢?下面我们开始创建main函数:

int main()
{
    // 创建Student的对象并让指针s1指向这个对象
    Student *s1 = [Student new];
    
    // 设置_name的值
    [s1 setName:@"张三"]; // 设置_age的值
    [s1 setAge:23];
    // 执行s1对象的eat方法
    [s1 eat];
    
    return 0;
}


从上面我们可以看出,main函数的中创建了Student类的对象s1,并且能够通过s1去设置Person中的_name值并且调用Person中的eat方法。这说明了在Student类中我们可以调用父类的属性和方法,这里我们称Person类为Student的父类,Student类为Person类的子类。

那么继承有什么好处呢?

1. 我们可以明确地表示两个类之间的关系。

2. 子类可以继承父类的属性和方法,提高了代码的复用率。

但是继承也有一个坏处,那就是会增加程序的耦合性。也就是说当有一天我们如果删除了Person类,那么Student类也将不能再使用,这就是继承的缺点。

子类从继承父类继承过来的方法也可以进行重写,下面就是对Person类中的eat方法的重写:

@implementation Student
- (void) setNo:(int)no
{
    _no = no;
}
- (int) no
{
    return _no;
}

// 重写eat方法
- (void) eat
{
    NSLog(@"%@今年%d岁了,他现在正在吃饭", _name, _age);
}
@end

重写eat方法后我们再在main函数中调用s1对象的eat的方法时就会调用重写后的eat方法。这时会输出:张三今年23岁了,他现在在吃饭。

继承的注意点:

1. 父类必须声明在子类的前面。

2. 子类的不能重写成员变量,因为子类中不允许有跟父类同名的成员变量。

3. 继承不是两个类有相同的属性和方法就可以确定继承关系的。比如说狗中有名字和年龄属性,还有跑和吃饭的方法,这些属性和方法人也可以拥有,但是可以让人继承狗这个类嘛,所以继承还要考虑事物之间的关系。

super的用法:

super是用来调用父类的方法的。它可以被用来调用父类中被子类重写的方法。比如说给上面的代码中重写的eat方法中再加上一句代码:

// 重写eat方法
- (void) eat
{
    [super eat];
    NSLog(@"%@今年%d岁了,他现在正在吃饭", _name, _age);
}
@end

上面的代码就是在子类的方法中调用了父类的方法。一般我们都是用来调用被重写的代码,因为没有被重写的代码我们的子类可以直接调用。

下面我们来学习多态。多态顾名思义就是一个对象有多种的形态,也就是说一个父类的对象既可以传入父类的对象也可以传入子类的对象。下面我们利用代码学习一下多态的用法。

#import <Foundation/Foundation.h>

// Person类的声明和实现
@interface Person : NSObject
{
    int _age;
}

- (void) setAge:(int)age;
- (int) age;
- (void) eat;
@end
@implementation Person
- (void) setAge:(int)age
{
    _age = age;
}
- (int) age
{
    return _age;
}
- (void) eat
{
    NSLog(@"吃饭了");
}
@end

// Student类的声明和实现
@interface Student : Person
{
    double _score;
}

- (void)setScore:(double)score;
- (double)score;
- (void)run;
@end
@implementation Student
- (void)setScore:(double)score
{
    _score = score;
}
- (double)score
{
    return _score;
}
- (void)run
{
    NSLog(@"跑起来了");
}
@end

int main()
{
    // 多态的实现,父类的指针指向子类的对象
    Person *p = [Student new];
    [p eat];
    Student *s = (Student *)p;
    [s run];
    
    return 0;
}

多态的特点:

1、没有继承就没有多态。

2、父类类型的变量不能直接调用子类的方法,必须要强制转化为子类类型才可以。

3、如果函数和方法形参列表中是父类的类型,则可以传入父类或子类的对象。

上面就是继承和多态的介绍。


总结:

1、继承是指一个类完全地拥有类另一个类的属性和方法。

2、继承时子类可以重写父类的方法,如果要调用父类的方法,可以用super。

3、继承不可以乱用,我们要理解两个类之间的关系,不是一个类有了另一个类的属性和方法就可以继承的。

4、继承只允许单继承,不能够同时继承多个类。

5、多态是在继承的基础上实现的。

6、多态可以在运行时根据对象的类型动态调用方法。

7、多态不可以直接调用子类的属性和方法。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值