zoukankan      html  css  js  c++  java
  • Objective-C 【继承、变量修饰符(私有变量/方法)、description方法】

    ———————————————————————————————————————————
    继承

    一段代码:

    #import <Foundation/Foundation.h>

    @interface Animal : NSObject
    {
        int _age;
    }
    -(void)setAge:(int)age;
    -(void)eat:(NSString *)foodName;
    -(void)run;
    @end

    @interface Dog : Animal
    -(void)lookHome;
    @end

    @interface JunDog : Dog
    -(void)zhaDiaobao;
    @end

    @implementation Animal
    -(void)setAge:(int)age
    {
        _age=age;
    }
    -(void)eat:(NSString *)foodName
    {
        NSLog(@"eat sth. about %@",foodName);
    }
    -(void)run
    {
        NSLog(@"run!!!he is %d years old!!!",_age);
    }
    @end

    @implementation Dog
    -(void)lookHome
    {
        NSLog(@"lookHome!");
    }
    @end

    @implementation JunDog
    -(void)zhaDiaobao
    {
        NSLog(@"zhaDiaobao!!");
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
    //        JunDog 是 Dog类 的派生类,他虽然没有直接继承于Animal,但是因为Dog继承了Animal,所以JunDog可以调用Animal中的方法和成员变量
            JunDog *jd=[JunDog new];
            
            [jd setAge:3];
            [jd run];
        }
        return 0;
    }


    //                                                                                                                       该类类名
    //继承就两点,①导入父类的头文件  ②在这里后面写上父类名    @interface  className : 父类名 …… @end


    ———————————————————————————————————————————
    基类和派生类之间的关系

    派生类方法属性=基类方法和属性+派生类自己新增的方法和属性

    注意:

    ①★★★基类的私有属性能被继承,但是不能访问(@private类型的变量是能够被继承的,但是不允许访问。可显示变量名说明能继承,访问在提示的时候是会有红色线标记说明无法访问)





    ②★★★OC中的继承是 单继承 的,也就是说一个类只能有一个父类,不能继承多个父类
    ③★继承的合理性,不能乱继承,人不能继承狗,狗也不能继承人。(合乎逻辑性)

    一段代码:

    #import <Foundation/Foundation.h>

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

    @implementation Animal
    -(void)eat
    {
        NSLog(@"animal eat!");
    }
    @end

    @interface Dog : Animal
    -(void)eat;//这句话可以不写,我们可以直接写方法的实现部分(这里的eat:方法是重写之后的eat:方法,是继承父类的eat:方法,不属于私有方法,所以不写声明也可以)
    //在Dog的父类Animal中有eat:方法,但是在Dog类中又重新定义了一下,这就叫做方法的重写。
    @end

    @implementation Dog
    -(void)eat
    {
        NSLog(@"dog eat!");
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Animal *ani=[Animal new];
            
            [ani eat];//ani对象调用的是Animal类中的eat:方法
            
            Dog *dog=[Dog new];
            
            [dog eat];//dog对象调用的是Dog类中的eat:方法(这里的eat:方法,是自己类中重写的)
    //        在类的实例对象调用方法的时候,先查看自己本类中有没有该方法,如果该类中有,就先调用自己的,如果没有就去其父类中寻找,如果父类中再没有,那么再往上一层去寻找,找到后就执行,但是如果到NSObject中还没有的话就报错了。这里可以看成是就近原则。
        }
        return 0;
    }


    ———————————————————————————————————————————
    继承的一些注意事项

    ①子类不能定义和父类同名的变量,但是可以继承父类的变量。
    如:我在Animal类中定义_age变量,然后Dog类继承Animal类,那么Dog类中是不能再定义一个_age变量的

    ②OC类支持单一继承,不支持多继承

    ③OC类支持多层继承

         动物类:Animal ——> 狗类:Dog ——> 军犬类:JunQuan


    ———————————————————————————————————————————
    实例变量修饰符

    访问修饰符:
    @public:任意程序集
    @protected:该类和其派生类(子类)  (如果声明时未做说明,那默认为是protected类型)
    @private:该类     (@private类型的变量只能被继承但是不能访问,也就是说在子类中访问private类型的变量的时候,你只能看见提示有这个变量,但是上面有一道红线,表示无法被访问)
    @package:框架级别的,作用域介于私有和公开之间,处于同一个框架之内就可以直接通过变量名访问


    ———————————————————————————————————————————
    OC中的私有变量

    在类的实现中(也就是.m文件中),也是可以声明成员变量的,但是在.m文件中声明的成员变量是@private(“纯/绝对”私有变量,既不能被继承,也不能被访问),而且在.m文件中声明的成员变量不能和.h文件中的成员变量同名,在这期间,即使是使用了@public等关键字修饰也是徒劳的。(也就是只能是@private类型的!!!)

    总结一下上面的一段话:
    ①在.m文件中声明成员变量不能和.h文件中的成员变量同名。
    ②在.m文件中声明的成员变量只能是@private类型的。


    一段代码:

    #import <Foundation/Foundation.h>

    @interface Animal : NSObject
    -(void)run;
    @end

    //无论在.m文件中的哪个位置定义一个新的变量,都是绝对私有变量,无法被其他类继承和访问
    int b=20;
    @implementation Animal
    int a=10;
    -(void)run
    {
        int c=30;
        NSLog(@"a=%d,b=%d,c=%d",a,b,c);
    }
    @end

    @interface Dog : Animal

    @end

    @implementation Dog
    -(void)run
    {
    //   NSLog(@"a=%d,b=%d",a,b);  //这样用是会报错的,因为a,b没有被继承过来
    //   NSLog(@"c=%d",c);  //显然c也没有被继承过来
    }

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Animal *ani=[Animal new];
            [ani run];
        }
        return 0;
    }


    建议大家一定要把代码拷贝到自己的Xcode中运行一下,即使很简单,也看看怎么得出的。


    ———————————————————————————————————————————
    OC中的私有方法

    在.h文件中没有声明,但是在.m文件中实现的方法,叫做私有方法。私有方法无法被子类继承和访问。


    一段代码:

    #import <Foundation/Foundation.h>

    @interface Person : NSObject
    -(void)eat;
    @end

    @implementation Person
    -(void)eat
    {
        NSLog(@"eat!");
        
        [self run];//①
        
        Person *p = [Person new];//②
        [p run];
    }

    -(void)run//既然这是一个私有方法,那我们应该如何去用他呢?经过在上面eat:方法中的测试,我们得到两种办法:
    //①我们利用self在.m文件中的其他可访问的方法下访问
    //②我们在.m文件中的其他可访问的方法下去实例化一个当前类的对象,然后用该对象调用这个私有方法(此时我们是在.m文件中实例化的这个对象,所以是可以访问run:方法的)
    {
        NSLog(@"run!!!!!");
    }
    @end

    @interface Student : Person

    @end

    @implementation Student

    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Student *st=[Student new];
            [st eat];
    //        [st run];//run:方法是在Person类(Student的父类)的.m文件中实现的,并没有在.h文件中声明,所以run:方法是一个Person类的私有方法。所以无法被其子类Student继承和访问
            Person *p=[Person new];
            [p eat];
    //        [p run];//这个地方也不能调用,就算是在main函数前加上 #import "Person.m" 也是不能用的。这是为什么呢?其实,有很多类,我们只提供给别人一部分可访问的东西,这些东西都在@interface @end中声明了,这就是一个接口,而我们不想让别人访问的,就不必声明。就像这个私有方法我们只是在.m文件中实现了而没有去声明一样。

        }
        return 0;
    }


    ———————————————————————————————————————————
    description方法——一个打印对象信息的方法


    一段代码:

    @interface Dog : NSObject
    //@property (readonly, copy) NSString *description;  在NSObject类中我们打开之后发现里面有这么一句话,这个东西虽然暂时看是一个对象,但是里面解开之后底层是一个名为description的对象方法。用作输出对象的信息。我们还可以在.m文件中对这个方法进行重写。
    {
        int _age;
        int _color;
    }
    -(void)setAge:(int)age;
    -(int)age;

    -(void)setColor:(int)color;
    -(int)color;

    -(void)run;


    @end

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

    -(void)setColor:(int)color
    {
        _color=color;
    }
    -(int)color
    {
        return _color;
    }

    -(void)run
    {
        NSLog(@"run!");
    }


    //重写description方法
    //这里我觉得可以看成是一个description的get方法,因为这个方法就是返回一个NSString类型的值
    -(NSString *)description
    {
        return [NSString stringWithFormat:@"_age:%d,_color:%d",_age,_color ];
    //    这里是调用了NSString类的一个字符串格式化输出的类方法
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            //首先我们知道description是 描述 的意思,所以说这个方法是用来 打印对象信息 的。
            Dog *dog = [Dog new];
            [dog run];
            
            NSLog(@"%p",dog);//0x100206790   结果是一个字符串,我们知道,这里是打印对象dog的地址,用%p
            
            [dog setAge:12];
            [dog setColor:1];
            NSLog(@"%@",dog);//<Dog: 0x100206790>   这里用%@格式打印出来的是这样一个字符串,显然里面的一些数字表示的dog对象的地址,与上面我们打印的地址是一样的。这里其实是打印的dog对象的信息,而这里调用了一个description方法,这个方法是一个对象方法,其格式是这样子的。每当我们用%@的格式打印对象,都会出现这样的信息。但是我们在Dog类中并没有写description这个方法啊?答案就是这个方法存在于NSObject类中。
        }
        return 0;
    }


    ———————————————————————————————————————————

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    [转]Session and application state in ASP.NET Core
    [转]Asp.net Core中使用Session
    [转]Cookie/Session机制详解
    [转] asp.net core Introducing View Components
    [转]ASP.NET Core 十种方式扩展你的 Views
    [转]asp.net core视图组件(ViewComponent)简单使用
    [转]ASP.NET Core集成微信登录
    [转].Net Core上用于代替System.Drawing的类库
    [转]【无私分享:ASP.NET CORE 项目实战(第十四章)】图形验证码的实现
    [转]在离线环境中发布.NET Core至Windows Server 2008
  • 原文地址:https://www.cnblogs.com/wzy294250051/p/4787895.html
Copyright © 2011-2022 走看看