黑马程序员_封装继承多态

---------------------- ASP.Net+Unity开发 .Net培训 、期待与您交流!----------------------

封装

        OC的封装和其他面向对象的语言相似,都是把自己的内部实现同外部屏蔽。封装的代码实现一部分功能供外部调用。封装的好处就是屏蔽内部的实现细节,方便外部调用。同时出于安全性考虑,封装可以防止一些重要的成员变量被修改。

1.set和get方法

        OC中的set方法和get方法都是对成员变量的操作方法,其中,set方法是设置成员变量的值,而get方法是获取成员变量的值。

#import <Foundation/Foundation.h>

@interface Student : NSObject
{
    int _age;
    NSString *_name;
}

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

- (void)setName:(NSString *)name;
- (NSString *)name;
@end

@implementation Student
- (void)setAge:(int)age
{
    _age = age;
}

- (int)age
{
    return _age;
}

- (void)setName:(NSString *)name
{
    _name = name;
}

- (NSString *)name
{
    return _name;
}
@end

int main()
{
    Student *stu = [Student new];
    
    [stu setAge:10];
    NSLog(@"age = %d",[stu age]);
    
    [stu setName:@"lsmseed"];
    NSLog(@"name = %@",[stu name]);
    
    return 0;
}

        运行结果:

2014-05-30 15:31:19.759 set[1484:303] age = 10
2014-05-30 15:31:19.762 set[1484:303] name = lsmseed

        set方法和get方法一般将成员变量以下划线开头命名,以便传值时区分变量。其中,set方法没有返回值,传入的变量给成员变量赋值后结束调用。get方法有返回值。

2.self关键字的使用

        self一般代指本类对象,主要出现在类的方法中,不能在函数中出现。self可以调用类方法,也可以调用对象方法。self访问成员变量时,可以和同名的局部变量相区分。

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    int _age;
    int _score;
    NSString *_name;
}

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

- (void)setScore:(int)score;
- (int)score;

- (void)setName:(NSString *)name;
- (NSString *)name;

- (void)test;
- (void)test1;
@end

@implementation Person
- (void)setAge:(int)age
{
    _age = age;
}

- (int)age
{
    return _age;
}

- (void)setScore:(int)score
{
    _score = score;
}

- (int)score
{
    return _score;
}

- (void)setName:(NSString *)name
{
    _name = name;
}

- (NSString *)name
{
    return _name;
}

- (void)test
{
    self->_age = 20;
    NSLog(@"age = %d score = %d name = %@",_age,_score,_name);
    [self test1];
}

- (void)test1
{
    NSLog(@"lsmseed");
}
@end

int main(int argc, const char * argv[])
{
    Person *p = [Person new];
    
    [p setAge:10];
    NSLog(@"age = %d",[p age]);
    
    [p test];
   
    return 0;
}

        运行结果:

2014-05-30 16:04:59.679 ds[1569:303] age = 10
2014-05-30 16:04:59.682 ds[1569:303] age = 20 score = 0 name = (null)
2014-05-30 16:04:59.686 ds[1569:303] lsmseed

        self代指本类调用了test1的方法,由于调用test方法的调用者是对象p所以self指代p间接的调用了test1的方法。同时,self也指代p对象间接的修改成员变量的值。如果self在test方法中又调用自己也就是[self test],那么程序将出现死循环现象。

3.类方法的声明和实现

        类方法区别与平常使用的对象方法。类方法就是用类名调用的方法,不能用对象名称来调用。类方法不同于对象方法的地方,主要是类方法不能访问成员变量。对象方法可以通过创建对象访问成员变量。

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    int _age;
    int _score;
    NSString *_name;
}

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

- (void)setScore:(int)score;
- (int)score;

- (void)setName:(NSString *)name;
- (NSString *)name;

+ (void)test;
+ (void)test1;
@end

@implementation Person
- (void)setAge:(int)age
{
    _age = age;
}

- (int)age
{
    return _age;
}

- (void)setScore:(int)score
{
    _score = score;
}

- (int)score
{
    return _score;
}

- (void)setName:(NSString *)name
{
    _name = name;
}

- (NSString *)name
{
    return _name;
}

+ (void)test
{
    //NSLog(@"%d,%d,%@",_age,_score,_name);
    [self test1];
}

+ (void)test1
{
    NSLog(@"lsmseed");
}
@end

int main(int argc, const char * argv[])
{
    Person *p = [Person new];
    
    [p setAge:10];
    NSLog(@"age = %d",[p age]);
    
    [Person test];
   
    return 0;
}

        运行结果:

2014-05-30 16:26:16.905 ds[1586:303] age = 10
2014-05-30 16:26:16.909 ds[1586:303] lsmseed

        类方法不能访问成员变量,但是通过self可以间接调用其他类方法。类方法执行效率较高,可以当工具方法使用。类方法也不能调用自己本身,如果出现[Personl test],程序也将出现死循环。如果代码中什么都不做,程序将直接推出报错。

继承

        继承是面向对象语言中的一个重要性质。继承可以保留原有类的基础,在此之上做方法和需求的拓展。被继承的类叫父类,继承者则是子类。子类中包含了父类中的方法和成员变量。

#import <Foundation/Foundation.h>

@interface Animal : NSObject
{
    int _count;
    NSString *_name;
}

- (void)eat;
- (void)run;
@end

@implementation Animal
- (void)eat
{
    NSLog(@"Animal eat %d",_count);
}

- (void)run
{
    NSLog(@"seed is run");
}
@end

@interface Dog : Animal
{
    int score;
}
@end

@implementation Dog

@end

@interface Cat : Animal

@end

@implementation Cat

@end

int main()
{
    Dog *d = [Dog new];
    [d run];
    
    Cat *c = [Cat new];
    [c eat];
    
    return 0;
}

        运行结果:

2014-05-30 16:40:16.277 jc[1633:303] seed is run
2014-05-30 16:40:16.280 jc[1633:303] Animal eat 0

        从上面的程序可以看出,Dog和Cat都继承了Animal这个类,也包含了这个类的成员变量和方法。被继承的类成了Dog和Cat的公有的部分。继承可以抽取公有的部分作为许多类的父类,这样其他类在拓展方法时彼此间都有一定的联系。OC的继承是单继承,不能同时继承多个类。子类继承父类,子类中的成员变量不能与父类重名。如果子类中的方法与父类重名,子类的方法覆盖父类中的方法,也可以使用super关键字来调用父类中的方法。

#import <Foundation/Foundation.h>

@interface Animal : NSObject
{
    int _count;
    NSString *_name;
}

- (void)eat;
- (void)run;
@end

@implementation Animal
- (void)eat
{
    NSLog(@"Animal eat %d",_count);
}

- (void)run
{
    NSLog(@"seed is run");
}
@end

@interface Dog : Animal
{
    //int _count;
    int score;
}
- (void)run;
@end

@implementation Dog
- (void)run
{
    [super run];
    NSLog(@"dog is running");
}
@end

@interface Cat : Animal
- (void)test;
@end

@implementation Cat
- (void)test
{
    [self run];
}
@end

int main()
{
    Dog *d = [Dog new];
    [d run];
    
    Cat *c = [Cat new];
    [c eat];
    [c test];
    
    return 0;
}

            运行结果:

2014-05-30 16:55:45.367 jc[1665:303] seed is run
2014-05-30 16:55:45.370 jc[1665:303] dog is running
2014-05-30 16:55:45.371 jc[1665:303] Animal eat 0
2014-05-30 16:55:45.372 jc[1665:303] seed is run

        继承使得类之间的耦合性增强,其中Cat这个类调用run方法时直接调用了父类中的run方法。而Dog类中有自己的run方法,所以屏蔽了父类中的方法,但是还是可以使用super先调用父类中的方法。继承保留了原有类的性质,使类在原有的基础上拓充。但是继承的类在增加方法时,要注意父类中的成员变量和方法,不能破坏原有的东西。


多态

        多态以继承为基础,没有继承就没有多态的使用。多态是继承的性能发挥和延伸体现。多态简单来说就是一个类可以有多种表现形式。多态的作用可以实现一个类接收不同类作为参数节省代码开销。

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    NSString *_name;
    int _age;
}

- (void)test;
- (void)print;

- (void)setName:(NSString *)name;
- (void)setAge:(int)age;
@end

@implementation Person
- (void)test
{
    NSLog(@"Person");
}

- (void)print
{
    NSLog(@"name = %@, age = %d",_name,_age);
}

- (void)setName:(NSString *)name
{
    _name = name;
}

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

@interface Student : Person
- (void)test;
@end

@implementation Student
- (void)test
{
    NSLog(@"student is Person");
}
@end

@interface Worker : Person
{
    int count;
}
@end

@implementation Worker
- (void)work
{
    NSLog(@"worker is working");
}
@end

void work(Person *p)
{
    NSLog(@"Person is %@",p);
    [p print];
    [p test];
}
int main()
{
    Person *p = [Person new];
    Person *s = [Student new];
    Person *w = [Worker new];
    
    
    Worker *ww = (Worker *)w;
    [ww work];
    Student *ss = (Student *)s;
    [ss test];
    
    work(p);
    work(s);
    work(w);
    return 0;
}

        运行结果:

2014-05-30 17:51:39.413 多态[1803:303] worker is working
2014-05-30 17:51:39.422 多态[1803:303] student is Person
2014-05-30 17:51:39.428 多态[1803:303] Person is <Person: 0x10010bd00>
2014-05-30 17:51:39.430 多态[1803:303] name = (null), age = 0
2014-05-30 17:51:39.431 多态[1803:303] Person
2014-05-30 17:51:39.435 多态[1803:303] Person is <Student: 0x100102e70>
2014-05-30 17:51:39.437 多态[1803:303] name = (null), age = 0
2014-05-30 17:51:39.438 多态[1803:303] student is Person
2014-05-30 17:51:39.439 多态[1803:303] Person is <Worker: 0x10010bf80>
2014-05-30 17:51:39.443 多态[1803:303] name = (null), age = 0
2014-05-30 17:51:39.445 多态[1803:303] Person

        多态体现了继承的作用,利用一个类来接收多个对象。但是父类引用在指向子类对象时,一般不能直接调用子类的方法,父类引用在调用时会检测对象的真实属性。所以最好把父类对象强制转化成子类再引用。

----------------------ASP.Net+Unity开发.Net培训、期待与您交流!----------------------


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值