Objective-C第三章封装和继承
你好!我是小柒,今天我们来学习一下面向对象三大特性的封装和继承。
封装
本节内容:
1、封装
2、继承
3、再谈self和super
4、方法重写
一、封装
小柒什么是面向对象的三大特性?
答:封装,继承,多态。
小柒什么是封装?
答:隐藏属性、方法或实现细节的过程称为封装。对象同时具有属性和方法两项特性,对象的属性和方法通常被封装在一起,共同体现事物的特性,二者相辅相承,不能分割。
例如:汽车的零件、发动机、地盘等都封装在汽车内部。
例如:两种或多种化学药品组成一个胶囊。信息隐藏,隐藏对象的实现细节,不让用户看到,将东西包装在一起,然后以新的完整形式呈现出来。
第一种:
// Student.h声明文件
#import <Foundation/Foundation.h>
@interface Student : NSObject
//1、当属性名和成员变量名一样时,如果我们对成员变量的值不强求,但我们又想打印赋上的值,这时在.m里可以使用_属性名 或者 self.属性名
{
// 成员变量
NSString *name;
}
@property NSString *name;
-(void)sayHi;
@end
//Student.m实现文件
#import "Student.h"
@implementation Student
-(void)sayHi
{
NSLog(@"name = %@ ",_name);
NSLog(@"name1 = %@",self.name);
}
@end
// main.m调用
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
stu.name = @"老王";
[stu sayHi];
}
return 0;
}
打印结果:
2015-12-29 20:20:13.899 OC3.13[3390:78731] name = 老王
2015-12-29 20:20:13.900 OC3.13[3390:78731] name1 = 老王
第二种:
// Student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
//2、当定义一个属性时,会首先查找是否有以_属性名命名的成员变量,如果有,则默认对其进行set和get,如果没有,则隐式生成以_属性名命名的变量
{
NSString *_name;
}
@property NSString *name;
-(void)sayHi;
@end
// Student.m
#import "Student.h"
@implementation Student
-(void)sayHi
{
NSLog(@"name = %@",_name);
NSLog(@"name11 = %@",self.name);
}
@end
// main.m
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
stu.name = @"老王";
[stu sayHi];
}
return 0;
}
打印结果:
2015-12-29 20:26:56.441 OC3.14[3554:82571] name = 老王
2015-12-29 20:26:56.442 OC3.14[3554:82571] name11 = 老王
第三种:
// Student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
//属性定义
@property NSString *name;
@property int age;
-(void)sayHi;
@end
// Student.m
#import "Student.h"
@implementation Student
@synthesize name,age;
//3、当属性名和成员变量名一样时,如果我们想保证成员变量有值,那么就需要在.m中加入@synthesize 变量名@synthesize name,age;
-(void)sayHi
{
NSLog(@"我是%@%d",name,age );
}
@end
// main.m
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
// 点语法
stu.name = @"老王";
stu.age = 12;
[stu sayHi];
}
return 0;
}
打印结果:
2015-12-29 20:30:05.913 OC3.12[3668:84857] 我是老王12
第四种:
// Student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
//4、当我们使用属性时,成员变量可以省略
@property NSString *name;
-(void)sayHi;
@end
// Student.m
#import "Student.h"
@implementation Student
-(void)sayHi
{
NSLog(@"name = %@",_name);
NSLog(@"name11 = %@",self.name);
}
@end
// main.m
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
stu.name = @"老王";
[stu sayHi];
}
return 0;
}
打印结果:
2015-12-29 20:31:49.480 OC3.15[3807:86304] name = 老王
2015-12-29 20:31:49.482 OC3.15[3807:86304] name11 = 老王
继承
二、继承
先看几个小例子:
食肉动物,食草动物,杂食动物;
出租车,大货车,大巴车;
苹果电脑,三星电脑,戴尔电脑;
小学生,中学生,打学生;
猜猜谁是父类
动物,汽车,电脑,学生
猜猜谁是子类
食肉动物、食草动物、杂食动物,苹果电脑、三星电脑、戴尔电脑,小学生、中学生、打学生。
以出租车,大卡车,大巴车为例:
车类:属性有品牌、颜色,方法有启动,刹车,加速减速。
出租车特性——打票,所属公司
大卡车特性——最大载重 ,卸货
大巴车特性——载客量大,报站
小柒什么是继承?
答:子类具有父类的一般特性(包括属性和行为),以及自身独特的特性,子类自动继承父类的属性和方法,被继承的类叫超类或父类,继承超类的类叫子类或派生类,且OC语言的类都是单继承,所有类最后的父类都是继承于NSObject。
小柒为什么需要继承?
答:编程时减轻代码量。
假如说,有两个类,他们有如下属性和方法
定义大卡车类:属性品牌,颜色,最大载重 方法:刹车,加速,卸货
定义出租车类:属性品牌,颜色,所属公司 方法:刹车,加速,打票
其实,这两个类的定义有什么问题?
答:代码存在重复
小柒有没有可能建立继承关系,让子类自动继承父类的属性和方法?
答:有继承关系,都是车,创建一个父类,就叫车类。
具体思路————
首先,我们可以创建3个类,一、创建父类,车类把共有属性和共有方法写在一起,二、创建两个子类,这样就能继承父类的属性和方法,大卡车类,出租车类,将特有的属性和特有大方法
写在大卡车类和出租车类里。
具体分类————
父类车类:共有的属性品牌、颜色,共有的方法刹车,加速
子类大卡车类:特有属性:最大载重 特有方法:卸货
子类出租车类:特有属性:所属公司 特有方法:打票
思路有了,我们回到Xcode,创建好一个工程,再创建一个父类,再创建子类。
操作步骤:
1、先创建好一个工程(Objective-C第一章类和对象中图1—4)
2、创建父类command+n创建父个类,第一项Class:父类名,注意第二项Subclass of:NSObject ,第三项Also不勾选,第四项Language:Objective-C/@interface car : NSObject
(Objective-C第一章类和对象中图9)
3、创建子类command+n创建一个子类,第一项Class:子类名,
注意:Subclass of:父类名,第三项Also不勾选,第四项Language:Objective-C/@interface Taxi : car
(如图1.1)
图1.1
具体代码————
// car.h
#import <Foundation/Foundation.h>
//父类
@interface car : NSObject
//品牌
@property NSString *Brand;
//颜色
@property NSString *Color;
//加速
-(void)speed;
//刹车
-(void)Brake;
//飞
-(void)fly;
@end
// car.m
#import "car.h"
@implementation car
-(void)speed
{
NSLog(@"我叫%@,颜色是:%@,我在加速",_Brand,_Color);
}
-(void)Brake
{
NSLog(@"我叫%@,颜色是:%@,我在减速",_Brand,_Color);
}
-(void)fly
{
NSLog(@"%@有抱负,天高任车飞",_Brand);
}
@end
// Taxi.h
//头文件不一样了
#import "car.h"
//子类出租车
@interface Taxi : car
//所属公司
@property NSString *company;
//打票
-(void)buy;
@end
// Taxi.m
#import "Taxi.h"
@implementation Taxi
//打票
-(void)buy
{
//self子类里面调用当前类方法,如果当前类没有,则调用父类方法。
//fly父类里面的方法
[self fly];
NSLog(@"%@是出租车,我能打票",self.Brand);
}
@end
// Truck.h
#import "car.h"
//子类货车
@interface Truck : car
//重量
@property int heft;
//卸货
-(void)unload;
@end
// Truck.m
#import "Truck.h"
@implementation Truck
-(void)unload
{
// super直接调用父类方法
//fly父类里面的方法
[super fly];
NSLog(@"%@是货车,到站了卸货吧",self.Brand);
}
//方法重写
//通过方法重写,子类可以改变从父类继承的行为。
//要求:被重写的方法定义必须与父类中的方法完全一样。
//父类方法
//加速
-(void)speed
{
NSLog(@"汽车没油了加毛线速啊");
}
@end
// main.m
#import <Foundation/Foundation.h>
#import "car.h"
#import "Taxi.h"
#import "Truck.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 父类
car *ar = [[car alloc] init];
ar.Brand = @"大黄";
ar.Color = @"白色";
[ar speed];
[ar Brake];
NSLog(@"__________________________");
// 子类
Taxi *taxi = [[Taxi alloc] init];
// 子类继承父类的品牌
taxi.Brand = @"老黑";
// 子类继承父类的颜色
taxi.Color = @"黑色";
// 子类继承父类的加速方法
[taxi speed];
// 子类继承父类的减速方法
[taxi Brake];
// 子类自己特有的方法打票
[taxi buy];
NSLog(@"__________________________");
Truck *truck = [[Truck alloc] init];
truck.Brand = @"汗血老马";
truck.Color = @"红色";
[truck speed];
[truck Brake];
[truck unload];
NSLog(@"__________________________");
}
return 0;
}
打印结果:
2015-12-30 14:33:53.848 Task[2856:113463] 我叫大黄,颜色是:白色,我在加速
2015-12-30 14:33:53.849 Task[2856:113463] 我叫大黄,颜色是:白色,我在减速
2015-12-30 14:33:53.849 Task[2856:113463] __________________________
2015-12-30 14:33:53.850 Task[2856:113463] 我叫老黑,颜色是:黑色,我在加速
2015-12-30 14:33:53.850 Task[2856:113463] 我叫老黑,颜色是:黑色,我在减速
2015-12-30 14:33:53.850 Task[2856:113463] 老黑有抱负,天高任车飞
2015-12-30 14:33:53.850 Task[2856:113463] 老黑是出租车,我能打票
2015-12-30 14:33:53.850 Task[2856:113463] __________________________
2015-12-30 14:33:53.850 Task[2856:113463] 汽车没油了加毛线速啊
2015-12-30 14:33:53.850 Task[2856:113463] 我叫汗血老马,颜色是:红色,我在减速
2015-12-30 14:33:53.850 Task[2856:113463] 汗血老马有抱负,天高任车飞
2015-12-30 14:33:53.850 Task[2856:113463] 汗血老马是货车,到站了卸货吧
2015-12-30 14:33:53.850 Task[2856:113463] __________________________
关键字self和super
三、再谈self和super
1、self子类里面调用当前类方法,如果当前类没有,则调用父类方法。 (代码在Taxi.m)
2、super直接调用父类方法。( 代码在Truck.m)
方法重写
四、方法重写
小柒什么是方法重写?
通过方法重写,子类可以改变从父类继承的行为。
要求:被重写的方法定义必须与父类中的方法完全一样。
( 代码在Truck.m)
哎呀!今天的课程又讲完了,大家好好敲代码,记得预习多态,小柒也吃饭了,拜拜。加油哦!