今天接着上一篇的继续写完,今天主要的内容是继承和多态。
一、self关键字
1)self关键字的用法主要有三点:
一是谁调用了当前方法,self就代表谁;self出现在对象方法中,self就代表对象; self出现在类方法中,self就代表类。
二是在对象方法利用”self->成员变量名”访问当前对象内部的成员变量。
三是[self 方法名]可以调用其他对象方法\类方法
先用代码来说明吧。
#import<Foundation/Foundation.h>
@interface Wife :NSObject//申明一个媳妇儿类
{
int face;//颜值
}
-(void)wash;
-(void)cook;
@end
@implementation Wife
-(void)wash
{
NSLog(@"帮我洗衣服");
}
-(void)cook
{
NSLog(@"给我做饭");
[self wash];//[self 方法名]可以调用其他对象方法\类方法
}
@end
int main()
{
Wife *My= [Wife new];//new一个媳妇儿对象
[My cook];//让媳妇儿执行这个方法
return 0;
}
运行得到
2)注意事项
当成员变量和局部变量同名时,采取就近原则,访问的是局部变量所以用self访问成员变量,区分同名的局部变量。
#import<Foundation/Foundation.h>
@interface Wife :NSObject//申明一个媳妇儿类
{
@public
int _face;//颜值
}
-(void)setFace:(int)face;
-(int)face;
-(void)wash;
-(void)cook;
@end
@implementation Wife
-(void)setFace:(int)face
{
_face=face;
}
-(int)face
{
return _face;
}
-(void)wash
{
NSLog(@"帮我洗衣服");
}
-(void)cook
{
NSLog(@"给我做饭");
[self wash];//[self 方法名]可以调用其他对象方法\类方法
}
-(void)test
{
int _face=200;
NSLog(@"颜值为%d的媳妇儿",_face);
}
@end
int main()
{
Wife *My= [Wife new];//new一个媳妇儿对象
[My setFace:100];
[My test];
[My cook];//让媳妇儿执行这个方法
return 0;
}
这里在test方法中用了和成员变量一样名字的局部变量,所以颜值face=200。
当用self->_face时,最后打印出来的就是face=200了。
3)self常见错误
1. 低级错误:用self去调用函数
2. 类方法中用self调用对象方法,对象方法中用self调用类方法
3. self死循环
这3项都是在使用self关键字时发生错误的地方,在这就不再累述了。
二、继承
在oc中,继承都是单继承的,举个形象的例子就是,我们的亲生双亲只有一个,你不可能是2个或2个以上杂交出来的。(感觉好无节操)而且子类不能和父类有相同的成员变量,这个很好理解,既然是继承,那父类有的子类也有了嘛。
1)继承的基本用法
#import<Foundation/Foundation.h>
@interface Animal : NSObject
{
int _age;
double _weight;
}
- (void)setAge:(int)age;
- (int)age;
- (void)setWeight:(double)weight;
- (double)weight;
@end
/********Animal的实现*******/
@implementation Animal
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
- (void)setWeight:(double)weight
{
_weight = weight;
}
- (double)weight
{
return _weight;
}
@end
/********Dog*******/
// : Animal 继承了Animal,相当于拥有了Animal里面的所有成员变量和方法
// Animal称为Dog的父类
// Dog称为Animal的子类
@interface Dog : Animal
@end
@implementation Dog
@end
/********Cat*******/
@interface Cat : Animal
@end
@implementation Cat
@end
int main()
{
Dog *d = [Dog new];
[d setAge:10];
NSLog(@"age=%d", [d age]);//狗的年龄为10
return 0;
}
运行结果
总之总结一下继承一些特点和注意事项。
1. 子类在父类的基础上拓充属性和方法
2. 子类方法和属性的访问过程:如果子类没有,就去访问父类的
3. 父类被继承了还是能照常使用的
4. 父类的静态方法
5. 画继承结构图,从子类抽取到父类
6. NSObject的引出:全部OC类的最终父类,包含了一些常用方法,比如+new。
2)方法的重写
子类重新实现父类中的某个方法,覆盖父类以前的做法。用一个代码来说明吧。
#import<Foundation/Foundation.h>
@interface plane:NSObject
{
int _weight;
}
-(void)setWeight:(int)weight;
-(int)weight;
-(void)fly;
+(void)fight;
@end
@implementation plane
-(void)setWeight:(int)weight
{
_weight=weight;
}
-(int)weight
{
return _weight;
}
-(void)fly
{
NSLog(@"飞机灰起来了");
}
+(void)fight
{
NSLog(@"灰机不会战斗");
}
@end
/*定义一个战斗机继承plane*/
@interface warPlane : plane
-(void)fly;
+(void)fight;
@end
@implementation warPlane
-(void)fly
{
NSLog(@"战斗机灰起来了");
}
+(void)fight
{
NSLog(@"战斗机可以战斗");
}
@end
int main()
{
warPlane *w =[warPlane new];
[w fly];
[warPlane fight];
plane *p =[plane new];
[p fly];
[plane fight];
return 0;
}
再来看看运行结果
可以看到warplane重写了方法fly和fight。
3)继承的一些特征
1. 不改变原来模型的基础上,拓充方法
2. 建立了类与类之间的联系
3. 抽取了公共代码
4. 坏处:耦合性强
三、super关键字
这个关键字简单,它的作用呢就是能 分别调用父类的对象方法和类方法。
super的作用
1. 直接调用父类中的某个方法
2. super处在对象方法中,那么就会调用父类的对象方法, super处在类方法中,那么就会调用父类的类方法。
- 使用场合:子类重写父类的方法时想保留父类的一些行为
#import<Foundation/Foundation.h>
@interface plane:NSObject
{
int _weight;
}
-(void)setWeight:(int)weight;
-(int)weight;
-(void)fly;
+(void)fight;
-(void)test;
+(void)test;
@end
@implementation plane
-(void)setWeight:(int)weight
{
_weight=weight;
}
-(int)weight
{
return _weight;
}
-(void)fly
{
NSLog(@"飞机灰起来了");
}
+(void)fight
{
NSLog(@"灰机不会战斗");
}
-(void)test
{
NSLog(@"调用父类 -test");
}
+(void)test
{
NSLog(@"调用父类 +test");
}
@end
/*定义一个战斗机继承plane*/
@interface warPlane : plane
-(void)useTest;
+(void)useTest;
@end
@implementation warPlane
-(void)useTest
{
[super test];//对象调用父类-test方法
}
+(void)useTest
{
[super test];//类对象调用匪类+test方法
}
@end
int main()
{
warPlane *w =[warPlane new];
// [w fly];
// [warPlane fight];
// plane *p =[plane new];
// [p fly];
// [plane fight];
[w useTest];
[warPlane useTest];
return 0;
}
这段代码中我分别用子类的对象方法和类方法调用父类的对象方法和类方法。
来看运行结果。
看!成功调用。
四、多态
多态字面上意思就是事物的多种形态。在面向对象中具体的表现就是子类对象可以赋值给父类指针和父类指针访问对应的属性和方法两种表现形态。具体看代码示例。
#import<Foundation/Foundation.h>
@interface Animal : NSObject
-(void)eat;
@end
@implementation Animal
-(void)eat
{
NSLog(@"Animal 能吃东西-eat");
}
@end
@interface dog :Animal
-(void)run;
-(void)eat;
@end
@implementation dog
-(void)run
{
NSLog(@"dog 跑起来了");
}
-(void)eat
{
NSLog(@"dog 吃起来了");
}
@end
int main()
{
Animal *a = [dog new];//调用方法时会检测对象的真实形态
[a eat];
//[a run]会出错 因为父类不能调用子类的方法和属性但是可以使用强转
dog *d = (dog *)a;
[d run];
return 0;
}
运行结果
如果直接用[a run]会出错 因为父类不能调用子类的方法和属性但是可以使用强转。我在代码中特别强调了这一点。
多态还可以节省代码,试想如果你顶一个函数,这里讲的是函数,而不是方法,这一点必须明确。比如:
(void)feed(Animal a)
{
[d eat];
}
这样写的话,是子类的可以传进来,父类也可以传进来,是不是节省了很多代码啊。
五、NSString的简单使用
快速创建NSString字符串
NSString *str =@"hello world";
int main()
{
NSLog(@"输出str%@",str);
return 0;
}
好了,今天的写完了。