OC面向对象三大特性


一、封装

封装其实是成员变量的封装,封装可以使外界不能直接访问成员变量,从而保证数据安全性。

set方法:

       作用:提供一个方法给外界设置成员变量值,可以在set方法中对参数进行过滤。

       命名规范:

1>方法名必须以set开头

2>set后面跟上成员变量的名称,且成员变量名称首字母必须大写

3>返回值一定是void

4>一定要接收一个参数,而且参数类型跟成员变量类型一致

5>形参的名称不要跟成员变量名一样

get方法:

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

命名规范:

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

2>方法名跟成员变量名一致

3>不需要接收任何参数

成员变量的命名规范
成员变量都以下划线 _ 开头
可以跟get方法的名称区分开,get方法名不加_
可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量

/*
 设计一个成绩类
 属性:
 C成绩,可读可写
 OC成绩,可读可写
 总分,只读
 平均分,只读
 
 */

#import <Foundation/Foundation.h>

@interface Score : NSObject
{
    double _cScore;
    double _ocScoer;
    double _sum;
    double _average;
}
- (void)setCSore:(double)cScore;
- (double)cScore;

- (void)setOCScore:(double)ocScore;
- (double)ocScore;

- (double)sum;

- (double)average;

@end


@implementation Score
- (void)setCSore:(double)cScore
{
    _cScore=cScore;
    _sum=_cScore+_ocScoer;//每设置一个成绩就将总分算一遍
}
- (double)cScore
{
    return _cScore;
}
- (void)setOCScore:(double)ocScore
{
    _ocScoer=ocScore;
    _sum=_cScore+_ocScoer;
}
- (double)ocScore
{
    return _ocScoer;
}
- (double)sum
{
    return _sum;
}
- (double)average
{
    return _sum/2;
}
@end

int main()
{
    Score *score=[Score new];
    [score setCSore:1];
    [score setOCScore:1];
    
    double sum=[score sum];
    double average=[score average];
    
    NSLog(@"sum-----%0.2f,average------%0.2f",sum,average);
    
    return 0;
}


二、类方法

不允许有相同的对象方法或者类方法,但是可以允许类方法和对象方法同名

对象方法中可以调用类方法。

对象方法:

  1>减号- 开头

  2>只能由对象来调用

  3>对象方法中能访问当前对象的成员变量(实例变量)

类方法:

  1>加号 + 开头

  2>只能由类来调用

  3>类方法中不能访问成员变量(实例变量)
类方法的好处和使用场合:

  1>不依赖于对象,执行效率高

  2>能用类方法尽量用类方法

  3>当方法中不需要使用到成员变量时,就可以改为类方法。

//设计一个计算器类,求和、求平均值方法

#import <Foundation/Foundation.h>

//工具类:基本没有成员变量,方法基本都是类方法
@interface jiSuanQi : NSObject
+ (int)sumWithNum1:(int)num1 andNum2:(int)num2;
+ (double)averageWithNum1:(int)num1 andNum2:(int)num2;
@end

@implementation jiSuanQi
+ (int)sumWithNum1:(int)num1 andNum2:(int)num2
{
    return num1+num2;
}

+ (double)averageWithNum1:(int)num1 andNum2:(int)num2
{
    return [jiSuanQi sumWithNum1:num1 andNum2:num2]/2.0;
}

@end


int main()
{
    NSLog(@"%d",[jiSuanQi sumWithNum1:23 andNum2:34]);
    NSLog(@"%0.2f",[jiSuanQi averageWithNum1:34 andNum2:54]);
    return 0;
}

三、self

1.概念:是个指针,指向当前对象(方法调用者)

2.用途:

    可以利用self->成员变量名 来访问当前对象内部的成员变量

    [self 方法名]可以调用其他对象方法或者类方法

注意:self和函数就不要掺合了

//设计一个计算器类,求和、求平均值方法

#import <Foundation/Foundation.h>

//工具类:基本没有成员变量,方法基本都是类方法
@interface jiSuanQi : NSObject
{
    int _num;
}
- (void)setNum:(int)num;

+ (int)sumWithNum1:(int)num1 andNum2:(int)num2;
+ (double)averageWithNum1:(int)num1 andNum2:(int)num2;
@end

@implementation jiSuanQi
- (void)setNum:(int)num
{
    _num=num;
}
- (void)test:(int)num
{
    int _num=num;
    
    //NSLog(@"%d",_num); 这是访问的这个方法中的_num
    NSLog(@"%d",self->_num);

}



+ (int)sumWithNum1:(int)num1 andNum2:(int)num2
{
    return num1+num2;
}

+ (double)averageWithNum1:(int)num1 andNum2:(int)num2
{
    //self代表当前类
    return [self sumWithNum1:num1 andNum2:num2]/2.0;
}

@end


int main()
{
    NSLog(@"%d",[jiSuanQi sumWithNum1:23 andNum2:34]);
    NSLog(@"%0.2f",[jiSuanQi averageWithNum1:34 andNum2:54]);
    
    
    jiSuanQi *j=[jiSuanQi new];
    [j setNum:23];
    [j test:90];
    return 0;
}

四、继承
继承的好处:

1>抽取重复代码

2>建立了类之间的关系

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

注意:基本上所有类的基类都是NSObject

继承使用注意:

1>父类声明要在子类前面(声明必须在前面,实现可以不在前面)

2>不允许子类和父类拥有相同名称的成员变量

3>子类和父类的方法可以同名。子类重新实现父类的某个方法叫重写,覆盖了父类的方法。

4>调用某个对象的方法时,优先去当前对象找,找不到再去父类找。

  类方法也满足这些。

5>内存中每个类都有个superclass指针,指针父类。在当前类找不到某个方法就会顺着这个指针去父类里找

继承的坏处:耦合性太强(两个类的关系太密切)

继承的使用场合:

1>当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个类中。

2>当A类拥有B类中的部分属性和方法时,可考虑让B继承A。

类之间的关系:

    继承——xx是xxx

    组合——xx拥有xxx

super作用:

1>可直接调用父类中的某个方法

2>若super在类方法中,就调用类方法

  若super在对象方法中,就调用对象方法

        3>使用场景:子类重写父类方法时,想保留父类的行为

/*
 定义三个类:Person、Student、Score(成绩)
 Student和Person是继承关系,Student和Score是组合关系
*/

#import <Foundation/Foundation.h>

//Score类
@interface Score : NSObject
{
    @public
    int _cScore;
}
- (void)setCScore:(int)cScore;
@end

@implementation Score
- (void)setCScore:(int)cScore
{
    _cScore=cScore;
}
@end

//Person类
@interface Person : NSObject
{
    int _age;
}
-(void)setAge:(int)age;
-(void)said;

+(void)live;
@end

@implementation Person
-(void)setAge:(int)age
{
    _age=age;
}
- (void)said
{
    NSLog(@"age=%d",self->_age);
}

+(void)live
{
    NSLog(@"eat and sleep");
}
@end

//Student类
@interface Student : Person
{
    //int _age; 不能喝父类拥有同名的成员变量
    char *_name;
    @public
    Score *score;
}

@end

@implementation Student


//重写父类的对象方法
- (void)said
{
    [super said];
    NSLog(@"cScore=%d",score->_cScore);
}


//重写父类方法
+(void)live
{
    NSLog(@"stady");
    [super live];//使用super关键字,调用父类的live方法,用来保留父类的某些行为
}

@end

int main()
{
    Student *student=[Student new];//创建Student对象
    Score *sc=[Score new];//创建Score对象
    student->score=sc;//给Student内部的score赋值
    [student setAge:23];
    [student->score setCScore:90];
    [Student live];
    [student said];
    

    return 0;
}
五、多态

    概念:没有继承就没有多态,即多态的前提是有继承。多态就是父类类型指针指向子类对象。

#import <Foundation/Foundation.h>

//Animal类
@interface Animal : NSObject
{
    int age;
}
- (void)eat;
@end

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

- (void)sleep
{
    NSLog(@"Animal--睡觉");
}

@end

//Dog类,继承Animal
@interface Dog : Animal
- (void)eat;
- (void)test;
@end

@implementation Dog
- (void)eat
{
    NSLog(@"Dog--吃");
}

- (void)test
{
    NSLog(@"咬人");
}

@end

//Cat类,继承Animal
@interface Cat : Animal
- (void)eat;
@end

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

@end

void feet(Animal *animal)//假如没有多态,那么这个参数类型将是Cat *或者Dog *。那么这个功能
{                       //用一个函数不能实现。因此多态的好处就显而易见
    NSLog(@"喂动物");

}

int main()
{
    Animal *a=[Dog new];//父类指针指向子类对象
    [a eat];//输出结果为 Dog--吃
     //程序运行时,会真正去确定a的真实类型,然后调用这个真实类型的方法,这是动态检测
    
    [a sleep];//由于Dog中没有这个方法,所以就调用父类的
    
    /*
    [a test];//编译时会警告可能没有这个方法,但是编译器是动态检测,所以程序可以正常运行.
            但是不建议这么做,父类类型的指针变量不能用来调用子类的特有方法。要想调用必须
            先强制转换
     */
    Dog *d=(Dog *)a;//类型强制转换
    [d test];
    
    feet(a);//调用函数
    
    return 0;
}
   总结:

1>没有继承就不会有多态

2>多态是父类指针指向子类对象

3>好处--函数/方法参数使用父类,实参可以是子类或者父类类型

4>父类类型指针不能直接调用子类特有方法,若想调用,必须先强制转换为子类类型。

5>父类类型指针调用子类方法,若子类已重写,那就调用子类的。子类没重写,那就是父类的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值