黑马程序员-6-Objective-C学习笔记(OC类的认识)
黑马程序员-6-Objective-C学习笔记(OC类的认识)
明天过后1 发表于3年前
黑马程序员-6-Objective-C学习笔记(OC类的认识)
  • 发表于 3年前
  • 阅读 39
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

摘要: 类,类的声明,@interface和@implementation 的分工和好处,类编写的一些规范,一些注意地方,self 关键字,super关键字

---------------------- Java培训.Net培训Android培训IOS培训、期待与您交流! ----------------------

注: 以下代码均为了省事,没有加入内存管理代码

1. 类

                之前已经了解了面向对象的思想了,在OOP中我们关注的重点是对象,那么接下来我们如何来得到我们想要的对象呢?日常生活中,以汽车为例,如果想得到一辆汽车首先要得到该汽车的设计图纸,然后根据图纸来            制造生产汽车,在编程中类相当于设计图纸,编译器相当于生产类的工厂,有了图纸有了工厂我们可以生产成千上万个类来使用。


2. 类的声明和实现

    /***************** car.h *****************/
    #import <Foundation/Foundation.h>    // 如果要使用OC面向对象的特性必须依赖于该框架
    
    // 类的声明
    @interface Car : NSObject            // @interface是告诉编译器这是类的声明的开始
    {                                    // : NSObject 声明该类继承与NSObject,NSObject是所有对象的根类它具备对象的实例化能力
    
        @public                          // @public 说明属相的访问权限为公有,就是可以通过指针来直接访问变量
                                         // @protected 如果不写则默认为 @protected 对于子类公开,就是子类方法中可以访问父类的属性
                                         // @package 只要处在同一个框架中,就能直接访问对象的成员变量
                                         // @private : 只能在当前类的对象方法中直接访问(@implementation中默认是@private)
        
        int _wheels; // 多少个轮子
        int _speed; // 时速
    }
    - (void)run; // 跑的行为
    @end                                 // @end是告诉编译器类声明完毕
    
    /***************** car.m *****************/
    #import "car.h"
    // 类的实现
    @implementation Car                  // @implementation告诉编译器类的实现开始
    - (void) run
    {
        NSLog(@"%i个轮子,%i时速的车子跑起来了", _wheels, _speed);
    }
    @end                                // @end类的实现结束
    
     /***************** main.h *****************/
    #import "car.h"
    
    int main(){
        Car *c = [Car new];
        c->_wheels = 4;
        c->_speed = 150; 
        [c run]; // 4个轮子,150时速的车子跑起来了
        return 0;
    }


3. @interface和@implementation 的分工和好处

    (1) 我们知道在C语言中函数一般我们提供函数的声明和实现,如果要调用该函数需要include该函数的头文件。

    (2) 在类中的@interface相当于函数的声明,用来告诉调用者该类的总体结构,和提供哪些功能。

    (3) 在@implementation中我们一般会把类的一些方法实现,一般这些细节的东西都不会对外公开的。

    (4) @interface 相当于一个产品的框架 ,@implementation相当于把该框架填充,可以用一下图来形象的表示(该图引自苹果官方文档)

            

    (5) 这样做的好处 : 

            1) 维护性好,如果某天要更改需求需要改变类的某个方法的实现,我们只需要更改该类的实现部分即可。

            2) 有利于版本升级,对于@implementation文件我们可以随着版本的升级提供不同版本的文件

            3) 清晰明了,调用者如果想快速了解该类只需要快速浏览该类的@interface文件,如果把声明跟实现写在同一个文件中将增加读取该类的难度。


4. 类编写的一些规范

    a. 属性命名规范

            (1) 属性命名要尽量有意义,而且尽量使用英文名词单词,对于复合单词用驼峰标识

            (2) 属性命名以下划线 _ 开头,在OC中一般以下划线来标识类的属性

            (3) 为了更好的可读性一般在属性定义后面加上注解(可选)。

    b. 属性的 settter 和 getter

            (1) setter :  - (void) set属性名(首字母大写去掉下划线):(属性类型)形参名称 ;

            (2) getter : - (属性类型) 属性名称(去掉下划线) ;

    // car.h
    #import <Foundation/Foundation.h>
    @interface Car : NSObject 
    { // 属性要写在大括号内
        int _wheels; // 多少个轮子
        int _speed; // 时速
    }
    - (void) setWheel:(int) wheel;
    - (int) wheel;
    - (void) setSpeed:(int) speed;
    - (int) speed;

    c. 方法的命名规范

            (1) - 代表对象方法 , + 代表类方法。对象方法调用依赖于类,类方法依赖于类

            (2) 声明和使用:

    // Car.h
    #import <Foundation/Foundation.h>
    #import "Person.h"
    @interface Car : NSObject 
    { // 属性要写在大括号内
        int _wheels; // 多少个轮子
        int _speed; // 时速
    }
    - (void) setWheel:(int) wheel;
    - (int) wheel;
    - (void) setSpeed:(int) speed;
    - (int) speed;
    // 一个人启动一辆车
    - (BOOL) startBy: (Person *) person;            // - 对象方法; (BOOL) 返回值类型 ; startBy: 方法名 ; (Person *) 参数类型 ; person 参数名称
    + (void) introduce;                             // + 类方法
    
    // Car.m
    ...
    
    // main.m
    
    #import "Car.h"
    #import "Person.h"
    int main(){
        [Car introduce];                            // 调用类方法
        Car *c = [Car new];                         // 对象的创建
        Person *p = [Person new];
        BOOL b = [c startBy: p];                    // 对象方法调用
        NSLog("start %@"( b ? @"success" : @"failed"));
        return 0;
    }


5. 一些注意地方

    a. 语法方面注意点 

           (1) 成员变量不能在{}中进行初始化、不能被直接拿出去访问

           (2) 方法不能当做函数一样调用

           (3) 成员变量\方法不能用static等关键字修饰,别跟C语言混在一起(暂时忽略)

           (4) 类的实现可用写在main函数的后面,主要在声明后面就行了

    b. 方法注意点

            (1) OC方法只能声明在@interface和@end之间,只能实现在@implementation和@end之间。也就是说OC方法不能独立于类存在

            (2) C函数不属于类,跟类没有联系,C函数只归定义函数的文件所有

            (3) C函数不能访问OC对象的成员

            (4) 低级错误:方法有声明,但是实现的时候写成了函数

            (5) 方法只有声明,没有实现(经典错误)

            (6) 方法没有声明,只有实现(编译器警告,但是能调用,OC的弱语法)

            (7) 编译的时候:访问没有的成员变量直接报错,访问没有的方法,只是警告


6. self 关键字

    a. self 初步认识

        在 java 和 C++ 中有 this 指针指向当前对象,因此我们可以通过 this 指针来访问该对象的成员变量和方法,一般该指针只限制于该对象的内部使用。OC 提供了self 关键字那么该关键字与this指针是否有相同的作用    呢?答案是否,该关键字指向的是调用者本身,那么该关键字可以用于对象方法(类似于java中的静态方法)中,但在 java 中this指针不能用于静态方法。

    b. 如何使用

    // Number.h
    #import <Foundation/Foundation.h>
    
    @interface Number: NSObject 
    {
        int _value;
    }
    - (void) setValue:(int)value;
    - (int) value;
    
    - (int) addWith:(Number *)num;
    + (int) num1:(Number *)n1 addWith:(Number *)n2;
    + (void) printAddResultWith:(Number *)n1 and:(Number *)n2;
    @end 
    
    // Number.m
    #import "Number.h"
    
    @implementation Number
    - (void) setValue:(int)value
    {
        self -> _value = value;                        // 在对象方法中self指向当前对象,因此可以通过该指针来访问成员变量
       
        // [self setValue:value];                     // 在某个方法中不能使用self调用该方法否则会引发死循环
    }
    - (int) value
    {
        return _value;
    }
    
    - (int) addWith:(Number *)num                        
    {
        return [self value] + [num value];             // 在对象方法中self指向当前对象,分别通过self指针访问成员变量 和 通过对象访问成员变量
    }
    
    + (int) num1:(Number *)n1 addWith:(Number *)n2
    {
        return [n1 value] + [n2 value];                
    }
    
    + (void) printAddResultWith:(Number *)n1 and:(Number *)n2
    {
        NSLog(@"the result is: %d"[self num1:n1 addWith:n2]);    // 在类方法中self指向当前类对象,因此它可以调用该类对象的类方法
    }
    @end


7. super关键字

    a. super初步认识

            同样在java中也有super关键字,不过要注意区分的地方跟 self 和 java中的this一样,super指向的是调用者父类的相应对象:

            对象方法 中 super 指向 的 父类对象 ,因此我们可以通过super关键字调用父类中的相应对象方法。

            类方法 中 super指向的是 父类的类对象 ,因此我们可以通过super关键字调用父类中相应的类方法。

    b. 如何使用

    /*
         Person.h
    */
    #import <Foundation/Foundation.h>
    
    @interface Person: NSObject
    {
        int _age;
    }
    - (void) setAge:(int)age;
    - (int)age;
    + (id) initWithAge:(int)age;                        // 声明一个构造方法返回一个OC对象的万能指针
    + (void) ageDesciption(Person *)p;
    @end
    
    /*
        Person.m
    */
    #import "Person.h"
    @implementation Person
    - (void) setAge:(int)age
    {
        self->_age = age;
    }
    - (int)age
    {
        return _age;
    }
    
    + (id) initWithAge:(int)age                        // 构造方法实现
    {
        id p = [[Person alloc] init];
        [p setAge:age];
        return p;
    }
    
    + (void) ageDesciption(Person *)p
    {
        if ( [p age] < 18 )
        {
            NSLog("青少年一个");
        } else {
            NSLog("非青少年");
        }
    }
    @end
    
    /*
             Student.h
     */
    #import "Person.h"
    
    @interface Student : Person                            // Student继承与Person类将拥有父类的属性和方法
    {
        NSString *_name;
    }
    - (void) setName:(NSString *)name;
    - (NSString *)name;
    + (id) initWithName:(NSString *)name andAge:(int)age;    // 声明一个构造方法
    + (void) introduceHimself;
    @end
    
    /*
             Student.m
     */
    #import "Student.h"
    
    @implementation Student
    
    - (void) setName:(NSString *)name
    {
        _name = name;
    }
    - (NSString *)name
    {
        return _name;
    }
    
    + (id) initWithName:(NSString *)name andAge:(int)age    // 构造方法实现
    {
        id s = [super age];                                // super当前指向Student类对象的父类对象
        [s setNmae:name];
        return id;
    }
    
    - (void) introduceHimself
    {
        int age = [super age];                            // super指向当前对象的父类对象
        NSLog("my name is %@, age is %d",_name,_age);
    }
    @end
    
    /*
        main.m
     */
     #import "Student.h"
     
     int main(){
     
        Student *s = [Student initWithName:@"jack" andAge:20];
        [s introduceHimself];
         return 0;
     }



---------------------- Java培训.Net培训Android培训IOS培训、期待与您交流! ---------------------- 

 详情请查看:http://edu.csdn.net/heima



  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 2
博文 20
码字总数 36166
×
明天过后1
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: