OC语言-02面向对象的三大特性

01封装

#import <Foundation/Foundation.h>


@interface Student : NSObject
{
    //@public  成员变量尽量不使用
    int _age;  //所有的成员变量以 _ 打头 与get方法的名称和局部变量进行区别
}
- (void)setAge:(int)age;  //set方法 提供给外界设置成员变量的值,可以在实现里对参数进行相应过滤
- (int)age;   //get方法 返回对象内部成员变量的值   如有get没有set那么这个成员变量就是只读的
- (void)study;
@end

@implementation Student
- (void)setAge:(int)age  //set方法必须以set开头,加成员变量名,变量名以大写开头
{
    if(age<=0 || age>100)  //利用set方法对参数的值进行必要的过滤
    {
        age = 1;
    }
    _age = age;
}

- (int)age
{
    return _age;
}

- (void)study
{
    NSLog(@"%d岁的学生开始学习!",_age);
}
@end

int main()
{
    Student *stu = [Student new];
    [stu setAge:35];
    [stu study];
    NSLog(@"此时成员变量_age的值是%d",[stu age]); //使用get方法来获取成员变量的值
    return 0;
}

类的方法

#import <Foundation/Foundation.h>

//工具类:基本没有 {成员变量(实例变量)[是要通过实例对象来调用的]},里面的方法基本都是类方法
//对象方法 以 - 开头 只能由对象来调用 可以访问当前对象的成员变量(实例变量)
//类方法  以 + 开头 只能由类名来调用 不可以访问成员变量,因为成员变量只有创建出实例对象后才创建
//能用方法的地方就使用类方法,效率要高,不用先去创建对象 当方法内部不需要使用成员变量的时候就使用类方法


@interface Calc : NSObject
+ (int)sumOfNum1:(int)num1 andNum2:(int)num2;
+ (int)averageOfNum1:(int)num1 andNum2:(int)num2;
@end

@implementation Calc
+ (int)sumOfNum1:(int)num1 andNum2:(int)num2
{
    return num1 + num2;
}
+ (int)averageOfNum1:(int)num1 andNum2:(int)num2
{
    int sum = [Calc sumOfNum1:num1 andNum2:num2]; //面向对象的思想,已经有方法可以实现加法了,不在(num1+num2)
    return sum / 2 ;
}
@end



int main()
{
    int sum = [Calc sumOfNum1:17 andNum2:19];
    int ave = [Calc averageOfNum1:19 andNum2:18];
    NSLog(@"sum=%d,average=%d",sum,ave);
    return 0;
}

 

  

02继承

1.重写:子类重新实现父类中的某个方法,覆盖父类以前的做法
2.注意
1> 父类必须声明在子类的前面
2> 子类不能拥有和父类相同的成员变量
3> 调用某个方法时,优先去当前类中找,如果找不到,去父类中找

2.坏处:耦合性太强  当删除了一个类,那么它的子类也无法使用

 

知识点:

1.每个对象里都有一个 isa指针 指向创建了它的类  低层原理是 isa指针这个成员变量是声明在NSObject中的,继承了它的子类创建的对象都有它的成员变量isa指针

2.每个类内都有一个 superclass指向了它的父类

#import <Foundation/Foundation.h>
/*
 1.继承的好处:
 1> 抽取重复代码
 2> 建立了类之间的关系
 3> 子类可以拥有父类中的所有成员变量和方法
 
 2.注意点
 1> 基本上所有类的根类是NSObject
 */


/********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*******/
// : 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]);
    return 0;
}

 有些情况下继承是不合理的  学生是分数 所以要使用<组合>

#import <Foundation/Foundation.h>

@interface Score : NSObject
{
    @public
    int _ocScore;
    int _cScore;
}
@end

@implementation Score
@end


@interface Student : NSObject
{
    @public
    Score *_score;
    int _age;
}

@end

@implementation Student
@end


int main()
{
    Student *stu = [Student new];
    stu->_age = 20;
    
    Score *s= [Score new];
    s->_ocScore = 89;
    s->_cScore = 90;
    
    stu->_score = s;
    
    NSLog(@"年龄是%d,oc分数是:%d",stu->_age,stu->_score->_ocScore);
    
    return 0;
}

 

03多态

/*
 1.没有继承就没有多态
 2.代码体现:父类类型的指针指向子类对象
 3.好处:如果函数/方法参数使用的是父类类型,可以传入 父类/子类对象
 4.注意:父类类型的变量不能直接调用子类特有的方法,要强转为子类类型变量后才能直接调用子类特有方法
 */

#import <Foundation/Foundation.h>

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

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


// 狗类
@interface Dog : Animal
- (void)eat; // 狗类重写了父类的 eat 方法
- (void)run; // 狗类独有的 run 方法
@end

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


// 猫类
@interface Cat : Animal
- (void)eat; //猫类重写的父类的 eat 方法
@end

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

//定义一个 喂 的函数
void feed(Animal *a) //注意传入的参数是父类指针
{
    //虽然父类指针中实际是动态绑定的真实对象,但编译器还是会认为它存着父类对象,所以,如果这个方法是子类独有的,父类中不存在这个 eat 方法 ,编译器会报警告,也许找不到 eat 方法
    [a eat];
}

int main()
{
    Dog *d = [Dog new];
    //虽接收者是父类指针,但程序会动态的绑定真实的对象,掉用对象中的方法
    feed(d);
    Cat *c = [Cat new];
    feed(c);
    
      Animal *a = [Dog new];
//    [a run]; //run 是狗独有的方法 编译时会报警告 在Animal中找不到 run方法
    
    Dog *dd = (Dog *)a; // 强转
    //[(Dog *)a run]; // 这样也是可以的 不用在额外声明一个指针
    [dd run];
    
    
    return 0;
}

 

posted @ 2015-12-21 11:10  呆而肥  阅读(195)  评论(0)    收藏  举报