黑马程序员--Objective-C之--OC面向对象的三大特征

 

------IOS培训期待与您交流! -------

 

OC面向对象的三大特征是封装、继承和多态。

OC语言也支持面向对象的三大特征,OC提供了@private、@package、@protected、@public等访问控制符来实现封装

OC也允许子类来继承父类,并且支持多态。

一、封装

封装指的是將对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法对内部信息的操作和访问。

OC的封装特性需要通过使用访问控制符来实现。

(一)、访问控制符

1、@private:当前类访问权限。如果类的成员变量使用@private访问控制符来限制,则这个成员变量只能在当前类的内部被访问。

这个访问控制符用于彻底隐藏成员变量。在类的实现部分定义的成员变量相当于默认使用这种访问权限。

2、@package:框架类访问权限。如果类的成员变量使用@package访问控制符来限制,则当前类或者同一框架中的其他类能够访问这个成员变量。

这个访问控制符用于部分隐藏成员变量。

3、@protected:子类访问权限。如果类的成员变量使用@protected访问控制符来限制,则当前类或者其子类能够访问这个成员变量。

这个访问控制符用于部分隐藏成员变量。

4、@public:公共访问权限。如果类的成员变量使用@public访问控制符来限制,则所有的类都能够访问这个成员变量。

这个访问控制符用于彻底暴露成员变量,一般不建议这么做。

(二)、set和get方法

类里面的绝大部分成员变量应该使用@private进行限制,提供set和get方法访问该成员变量。

1、set方法

(1)作用: 提供一个方法给外界设置成员变量值,可以在方法里面对参数进行相应过滤

(2)命名规范:

第一:方法名必须以set开头

第二:set后面跟上成员变量的名称,成员变量的首字母必须大写

第三:返回值一定是void

第四:一定要接收一个参数,而且参数类型跟成员变量类型一致

第五:形参的名称不能跟成员变量名一样

2、get方法

(1)作用:返回对象内部的成员变量

(2)命名规范:

第一:肯定有返回值,返回值类型肯定与成员变量类型一致

第二:方法名跟成员变量名一样

第三:不需要接收任何参数

 

@interface Student : NSObject
{ 
    @private
    int age;
}

- (void)setAge:(int)newAge;  //set方法,用来改变age的值
- (int)age; //get方法,用于获取age的值 @end @implementation Student // set方法的实现 - (void)setAge:(int)newAge { // 对传进来的参数进行过滤 if (newAge <= 0) { newAge = 1; } age = newAge; } - (int)age { return age; }
@end

 

二、继承

继承是面向对象的三大特征之一,也是实现软件复用的重要手段。OC的继承具有单继承的特点,每个子类只有一个直接父类。

(一)、继承的好处

1、抽取重复代码

2、建立了类之间的关系

3、子类可以拥有父类中的所有成员变量和方法

 

/********Animal的声明*******/
@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*******/
// : Dog 继承了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]);
    return 0;
}

 

(二)、重写父类方法

子类重新实现父类中的某个方法,覆盖父类中的方法叫做重写。子类重写父类的方法需要注意以下几点

第一:父类必须声明在子类的前面

第二:子类不能拥有和父类相同的成员变量

第三:调用某个方法时,优先去当前类中找,如果找不到,去父类中找

 

// Person
@interface Person : NSObject
{
    int _age;
}

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

- (void)run;

+ (void)test;

@end

@implementation Person

+ (void)test
{
    NSLog(@"Person+test");
}

- (void)run
{
    NSLog(@"person---跑");
}

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

// 不允许子类和父类拥有相同名称的成员变量
// Student
@interface Student : Person
{
    int _no;
    // int _age;
}

+ (void)test2;

@end

@implementation Student
// 重写:子类重新实现父类中的某个方法,覆盖父类以前的做法 - (void)run { NSLog(@"student---跑"); } + (void)test2 { [self test]; } @end int main() { [Student test2]; // Student *s = [Student new]; // // [s run]; return 0; }

 

(三)、super关键字

如果需要在子类方法中调用父类的方法,可使用super关键字。

super处在对象方法中,那么就会调用父类的对象方法; super处在类方法中,那么就会调用父类的类方法。

 

// 僵尸
@interface Zoombie : NSObject
- (void)walk;

+ (void)test;
- (void)test;

@end

@implementation Zoombie
- (void)walk
{
    NSLog(@"往前挪两步******");
}

+ (void)test
{
    NSLog(@"Zoombie+test");
}

- (void)test
{
    NSLog(@"Zoombie-test");
}
@end

// 跳跃僵尸
@interface JumpZoombie : Zoombie
+ (void)haha;
- (void)haha2;
@end


@implementation JumpZoombie

+ (void)haha
{
    [super test];
}

- (void)haha2
{
    [super test];
}

- (void)walk
{
    // 跳两下
    NSLog(@"跳两下");
    
    // 走两下(直接调用父类的walk方法)
    [super walk];
    //NSLog(@"往前挪两步----");

}
@end

int main()
{
    //[JumpZoombie haha];
    JumpZoombie *jz = [JumpZoombie new];
    
    [jz haha2];
    
    return 0;
}

 

三、多态

OC指针类型的变量有两个,一个是编译时的类型,一个是运行时的类型,编译时的类型是由声明该变量时使用的类型决定,运行时的类型由实际赋给该变量的对象决定。

如果编译时类型和运行时类型不一致,就出现多态。

 

// 动物
@interface Animal : NSObject
- (void)eat;
@end

@implementation Animal
- (void)eat
{
    NSLog(@"Animal-吃东西----");
}
@end

//
@interface Dog : Animal
- (void)run;
@end

@implementation  Dog
- (void)run
{
    NSLog(@"Dog---跑起来");
}
- (void)eat
{
    NSLog(@"Dog-吃东西----");
}
@end

//
@interface Cat : Animal

@end

@implementation Cat
- (void)eat
{
    NSLog(@"Cat-吃东西----");
}
@end

// 这个函数是专门用来喂动画
//void feed(Dog *d)
//{
//    [d eat];
//}
//
//void feed2(Cat *c)
//{
//    [c eat];
//}
//

// 如果参数中使用的是父类类型,可以传入父类、子类对象
void feed(Animal *a)
{
    [a eat];
}

int main()
{
    // NSString *d = [Cat new];
    // [d eat];
    
    /*
    Animal *aa = [Dog new];
    // 多态的局限性:父类类型的变量 不能用来调用子类的方法
    //[aa run];
    
    // 将aa转为Dog *类型的变量
    Dog *dd = (Dog *)aa;
    
    [dd run];
    */
    
    //Dog *d = [Dog new];
    
    //[d run];
    
    /*
    Animal *aa = [Animal new];
    feed(aa);
    
    Dog *dd = [Dog new];
    feed(dd);
    
    Cat *cc = [Cat new];
    feed(cc);
     */
    
    /*
    // NSString *s = [Cat new];
    Animal *c = [Cat new];
    
    
    NSObject *n = [Dog new];
    NSObject *n2 = [Animal new];
    
    
    // 多种形态
    //Dog *d = [Dog new]; // Dog类型
    
    // 多态:父类指针指向子类对象
    Animal *a = [Dog new];
    
    // 调用方法时会检测对象的真实形象
    [a eat];
    */
    return 0;
}

 

posted on 2015-03-28 00:15  waterfoxjie  阅读(279)  评论(0编辑  收藏  举报