面向对象三大特性: 封装 继承 多态
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式.
好处: 将变化隔离. 便于使用. 提高重用性. 提高安全性
原则: 将不需要对外提供的内容都隐藏起来.
把属性都隐藏,提供公共方法对其访问
方法默认就是用了封装的思想.
属性有两种方式操作:
1直接操作: public
2封装操作:通过给外部暴露两个方法:set方法用于设置值.get方法用于获取值.
一个属性的set与get方法不是必须的,看情况,如果你希望让外部调用者可以设置值,
则你就给定义set方法.如果你希望外部能获取值,就定义get方法. 一切看需求.
#import <Foundation/Foundation.h>
@interface Person : NSObject{
//@public 表示这个属性能被外部直接访问.
//属性命名规范: //属性名以_开头.
//以便于与参数区分.同时.便于与局部变量区别.
char *_name;
int _age;
}
-(void) smile;
/*规范: 1.
不能有返回值
.
2.必须有参数,且参数类型与属性类型一致.
3.参数名不能与属性名一致
4.set+属性名:首字母大写(驼峰命名)
作用:就是给属性(成员变量)去赋值 */
-(void) setAge:(int) age;
/* 规范: 1.
必须有返回值
.
2.不能有参数.
3.返回值类型必须跟属性类型一致.
4.get+属性名:首字母大写(驼峰命名)
作用:就是把属性值传递给调用者. */
-(int) getAge;
@end
@implementation Person
-(void) smile{
NSLog(@"%s笑了--年龄是:%d",_name,_age);
}
-(void) setAge:(int) age{
if(age<=0){
_age=1;
}else{
_age=age;
}
//NSLog(@"当前的年龄是:%d",age);
}
-(int) getAge{
return _age;
}
@end
int main(){
Person *p=[Person new];
// [p smile];
// p->name="fred";
//public的方式,外部拿到对象可以直接操作对象的属性,没有限制.
// p->age=-100;
[p setAge:100]; //用封装的方式去设置值
NSLog(@"当前的年龄是:%d",[p getAge]); //用封装的方式去获取值.
[p smile];
return 0;
}
类方法封装
不需要创建对象,可以直接通过类名调用的方法,称为类方法.
作用:
调用方便.执行效率高.在定义方法的时候尽量用类方法.
类方法不能使用属性--局限性.
定义方法时:
@interface Person : NSObject{
char *_name;
}
-(void)setName:(char *)name;
-(void)smile;
+(void)smile;
+(void)haha:(char *)str;
@end
@implementation Person
-(void)setName:(char *)name{
_name=name;
}
-(void)smile{
NSLog(@"哈哈..很开心..%s",_name);
}
+(void)smile{
NSLog(@"呼呼..很开心..");
}
+(void)haha:(char *)str{
NSLog(@"haha..很开心..%s",name);
}
@end
int main(){
Person *p=[Person new];
[p setName:"fred"];
[p smile];
// [p haha:"haha"]; //错误的
[Person haha:"heihei"];
[Person smile];
return 0;
}
到底是用类方法还是对象看在方法里是否要用到属性.
如果要用到属性则用对象方法.反之,用类方法.
self是<关键字> 用来<在类中调用方法.或属性>
调用方法:[self 方法名];
调用属性:self->属性名
self 可以在类中用来表示调用者,去调用方法.或属性.
什么时候用?
当需要在类的方法中调用方法或属性时
注意:当self调用属性时,只在对象方法中,因为类方法中不能用属性.
+(void)haha{
NSLog(@"haha..很开心..");
//self->_name;//错误,不能在类方法中访问属性
}
+(void)haha2{
//在类方法中,表示的是类
[self haha];
NSLog(@"haha222..很开心..");
}
-(void)smile{
char *_name="fred";
//self表示调用这个方法的对象.而对象->name.这个取的是属性.
NSLog(@"哈哈..很开心..%s",self->_name);
}
-(void)talk{
//smile;错误
//self:表示调用者.
[self smile];//如果self是在对象方法中,则表示这个类的对象.
NSLog(@"%s讲了一个笑话..",_name);
}
特点:1.在方法中不能调用方法自己2.只能类方法调用类方法,对象方法中调用对象方法,不能混淆
3.只能在对象方法中调用属性
+() 类方法
-() 对象方法
用self时,要注意:不要在方法中用self调用方法本身会产生死递归:方法自己调用自己,容易引起死循环.
继承
多个类中存在相同属性和行为时,将这些内容抽取到 单独一个类中,那么多个类无需再定义
这些属性和行为,只要继承单独的那个类即可.这种拥有另一个类是属性和方法的方式称为继承.
一个父类的子类可以是多个,但一个类的父类只能有一个.
作用及好处:
子类可以直接访问父类中的属性和行为.
继承的出现提高了代码的复用性.
继承的出现让类与类之间产生了关系,提供了多态的前提.
动物类
@interface Animal : NSObject{
int _legCount;//腿的数量
int _eyeCount;//眼睛数量
}
-(void)cry;
-(void)run;
-(void)eat;
-(void)sleep;
@end
@implementation Animal
-(void)cry{
NSLog(@"叫了...");
}
-(void)run{
NSLog(@"跑了...");
}
-(void)eat{
NSLog(@"吃了...");
}
-(void)sleep{
NSLog(@"睡了...");
}
@end
//狗--如果父类中没有,而子类又需要,则自已添加就可以了.--扩展.
@interface Dog : Animal
{
char *_nose;//狗独需的--鼻子
}
+(void)kanMen;
@end
@implementation Dog
+(void)kanMen{
NSLog(@"狗看门");
}
@end
//猫
//猫Cat是Animal的子类, Animal是Cat的父类
//一个子类继承了父类,则子类拥有父类的所有方法和属性
@interface Cat : Animal
-(void)setLegCount:(int)legCount;
-(int)getLegCount;
-(void)catchMouse;
@end
@implementation Cat
-(void)setLegCount:(int)legCount{
_legCount=legCount;
}
-(void)catchMouse{
NSLog(@"猫抓老鼠...");
}
-(int)getLegCount{
return _legCount;
}
@end
1.子类里不能定义与父类相同的属性.
2.但子类与父类可以定义相同的方法
3.当子类与父类有同名方法时,用子类的.
4.父类必须在子类定义前声名.
5.一个类只能单继承(一级继承),但是能多层继承(多级(间接)继承).且多层继承没有限制.
6.越下层的子类功能越强.
重写
属性不能重写,方法可以重写(写的是方法内容,其他不变)<父类方法不满足需要,子类方法重写>
***:任何的类都必须有new方法,才能够创建对象.new方法是在NSObject中,
是一个类方法:+ (instancetype) new
继承:子类与父类的关系-->子类 is 父类
不能只为了继承而继承,要考虑二者的从属关系.
组合:一个类里,包含另一个类的对象
<警察,,警犬>
当两个类不属于同一个类,但是又需要建立关联的时候,可以用组合.
表示:A类包含B类.
super的用法
在子类中调用父类中被重写的方法.
表示:调用父类中的方法.
多态
多态的表现:
父类类型的指针指向子类对象
如:Animal是父类,它有两个子类,Dog与Cat.
则Dog与Cat对象都可以这样表示:
Animal *a=[Dog new]; Animal *a=[Cat new];
*没有继承就没有多态—前题
作用及优点:增强扩展性!
1.一个类可以表示多种对象.如上面a即可以表示Dog或Cat对象.
2.如果方法或函数参数中使用的是父类类型可以传入父类、子类对象.
局限性:
父类类型的变量不能直接调用子类特有(重写的不算)的方法.
必须强转为子类类型后,才能直接调用子类特有的方法.
#import <Foundation/Foundation.h>
//父类--动物
@interface Animal : NSObject
-(void)eat;
@end
@implementation Animal
-(void)eat{
NSLog(@"动物吃东西...");
}
@end
//动物类的子类-狗
@interface Dog : Animal
-(void)eat;
-(void)kanMen;//狗狗独有的方法
@end
@implementation Dog
-(void)eat{
NSLog(@"狗吃东西...");
}
-(void)kanMen{
NSLog(@"狗看门...");
}
@end
//动物类的子类-猫
@interface Cat : Animal
-(void)eat;
@end
@implementation Cat
-(void)eat{
NSLog(@"小猫吃东西...");
}
@end
int main(){
//多态写法
//前题:
//1.必须是继承关系的类才可以.而且是父类的指针代表子类对象.
//父类指针指向子类对象,调用方法时,会自动找子类相对应的方法.
Animal *am=[Dog new];
//会有警告:因为父类中没有这个方法.不能这么用.这是多态的局限性.
// [am kanMen];
//用多态的方式调用子类的方法-->强转
Dog *tempDog=(Dog *)am;
[tempDog kanMen];
am=[Cat new];
[am eat];
return 0;
}