• OC语言基础知识


    一、面向对象

      OC语言是面向对象的,C语言是面向过程的,面向对象和面向过程知识解决问题的两种思考方式,面向过程关注的是解决问题涉及到的步骤,而面向对象关注的是设计能够实现解决问题所需功能的类。

      术语:OC面向对象    OPP面向对象编程

    二、类

    (一)关于类

      1>类是一个抽象的概念,而对象是一个真实存在的物体,一个对象包括两部分:属性跟方法

      2>类的设计最重要的三点:类名、  属性  、方法

      注意:一般名词都是类,拥有相同属性和行为的对象都可以抽象为一个类,类名是标识符的一种,需要符合规范,通常类名的第一个字母大写,且不能有下划线,如果由多个单词组成则使用驼峰法则。在OC中,对象对方法的调用称为消息机制,即向既定的对象发送了什么消息。

    (二)简单的内存分析

      1>类创建对象,每个对象在内存中都占据一定的存储空间,每个对象都有一份属于自己的单独的成员变量(属性或实例变量),所有的对象共用类的成员的方法,方法在整个内存中只有一份,类本身在系统中占据一份内存空间,类的方法存在于此。

      2>每个对象内部都默认有一个isa指针来指向这个对象所使用的类。

      3>[person(对象名) run(对象方法)]  表示:给person所指向的对象发送一条run消息,调用对象的run方法,此时对象会顺着内部的isa指针找到存储于类中的方法并执行。

      4>isa是对象中隐藏的指针,指向创建这个对象的类。

    (三)类的声明和实现

      1> 接口部分:@interface 声明了类于父类   以@interface编译指令为开始,以@end结束

          实现部分:@implementation   ...   @end

      2>类方法以+开头,如+(void) run;

      类的声明1:

    #import <Foundation/Foundation.h>
    
    @interface Student : NSObject{
        
        /** 学号*/
        NSInteger _no;   //勿忽略下划线
        /** 姓名*/
        NSString * _name;
        /** 成绩*/
        CGFloat _score;
        
    }
    
    //*********set get 方法*************
    
    /**
     *  学号set get方法
     *
     *  @param no 学号
     */
    -(void) setNo:(NSInteger) no;
    -(NSInteger) no;
    
    /**
     *  姓名方法
     *
     *  @param name 姓名
     */
    -(void) setName:(NSString *) name;
    -(NSString *) name;
    
    /**
     *  成绩方法
     *
     *  @param score 成绩
     */
    -(void) setScore:(CGFloat) score;
    -(CGFloat) score;
    
    
    //*************其他方法***************
    
    /**
     *  查询成绩方法
     */
    -(void) showScore;
    
    /**
     *  补考方法
     */
    -(void) reExam;
    @end

    以上声明可以用@property简化如下:

    #import <Foundation/Foundation.h>
    @interface Student : NSObject
    
    /** 学号*/
    @property NSInteger no;     //无需加下划线
    
    /**姓名*/
    @property NSString * name;
    
    /** 成绩*/
    @property CGFloat score;
    
    //*************其他方法***************
    
    /**
     *  查询成绩方法
     */
    -(void) showScore;
    
    /**
     *  补考方法
     */
    -(void) reExam;
    @end

    类的实现1:

    #import "Student.h"
    
    @implementation Student
    
    
    #pragma mark - 学号
    -(void) setNo:(NSInteger) no{
        
        _no=no;
        
    }
    -(NSInteger) no{
        
        return _no;
        
    }
    
    #pragma mark - 姓名
    -(void) setName:(NSString *) name{
        
        _name=name;
        
    }
    -(NSString *) name{
        
        return _name;
    }
    
    #pragma mark - 成绩
    -(void) setScore:(CGFloat) score{
        
        _score=score;
        
    }
    -(CGFloat) score{
        
        return _score;
        
    }
    
    
    //*************其他方法***************
    
    #pragma mark - 查询成绩
    -(void) showScore{
        
        NSLog(@"成绩:%g分",_score);
        
    }
    
    #pragma mark - 补考
    -(void) reExam{
        
        if (_score<60) {
            NSLog(@"补考");
        }else{
            NSLog(@"无需补考");
        }
    }
    @end

    类的调用:在主函数创建一个Student类型的对象(先调用alloc分配存储空间,然后调用init方法初始化为0),并定义了一个Student类型的指针指向创建的这个对象,之后用.语法初始化对象变量score的值为59,然手调用对象的reExam方法.

    #import <Foundation/Foundation.h>
    #import "Student.h"
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
           
            //初始化并赋值
            Student * stu=[[Student alloc] init];
            stu.score=59;
            
            //调用方法
            [stu reExam];
            
        }
        return 0;
    }

    练习题

    说明:

    属性: 坐席数量 剩余数量 票据信息,其中票据信息又包括电影名称 电影类型 开始时间 价格,实现当前上映电影的简介以及卖票,退票功能

    解析:票据信息Ticket需要新建一个类,并且将套入到Cinema类中

    Cinema类的声明

    #import <Foundation/Foundation.h>
    #import "Ticket.h"
    @interface Cinema : NSObject
    
    /** 坐席数量*/
    @property NSInteger seatNo;
    
    /** 剩余数量*/
    @property NSInteger leftNo;
    
    /** 票据信息*/
    @property Ticket * ticket;
    
    //************其他方法************
    
    /**
     *  卖票
     */
    -(void) sellTickets;
    
    /**
     *  退票
     */
    -(void) returnTickets;
    
    @end

    Ticket类的声明

    #import <Foundation/Foundation.h>
    
    @interface Ticket : NSObject
    
    /** 电影名称*/
    @property NSString * name;
    
    /** 电影类型*/
    @property NSString * type;
    
    /** 开始时间*/
    @property NSString * startTime;
    
    /** 价格*/
    @property CGFloat price;
    
    
    //***************其他方法************
    
    /**
     *  展示电影简介
     */
    -(void) showFilm;
    
    @end

    Cinema类的实现

    #import "Cinema.h"
    @implementation Cinema
    
    #pragma mark - 卖票
    -(void) sellTickets{
        
        //嵌套方法
        [_ticket showFilm];
        
        //卖票
        _leftNo-=1;
        NSLog(@"现有%ld张票,成功卖票1张,还剩%ld张",_seatNo,_leftNo);
        
    }
    
    #pragma mark - 退票
    -(void) returnTickets{
        
        //嵌套方法
        [_ticket showFilm];
        
        //退票
        _leftNo+=1;
        NSLog(@"现有%ld张票,成功退票1张,还剩%ld张",_seatNo,_leftNo);
    
    }
    @end

    Ticket类的实现

    #import "Ticket.h"
    
    @implementation Ticket
    
    #pragma mark - 展示电影简介
    -(void) showFilm{
    
        NSLog(@"
    电影名称:%@
    电影类型:%@
    开始时间:%@
    价格:%g",_name,_type,_startTime,_price);
        
    }
    
    @end

    调用

    #import <Foundation/Foundation.h>
    #import "Cinema.h"
    #import "Ticket.h"
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
           /*
            //初始化并赋值
            Student * stu=[[Student alloc] init];
            stu.score=59;
            
            //调用方法
            [stu reExam];
            */
            
            //初始化并赋值
            Cinema * cinema=[[Cinema alloc] init];
            cinema.seatNo=50;
            cinema.leftNo=50;
            
            Ticket * ticket=[[Ticket alloc] init];
            ticket.name=@"极限挑战";
            ticket.type=@"娱乐搞笑类";
            ticket.startTime=@"20:35";
            ticket.price=65.5;
            
            //调用
            [cinema sellTickets];
            [cinema returnTickets];
            
        }
        return 0;
    }

    (四)常见错误

      1>@interface  @end 和 @implementation @end不能嵌套包含

      2>只有类的声明,却没有类的实现

      3>漏写@end

      4>两个类的声明嵌套(可以把顺序打乱)

      5>成员变量没有写在{}内

      6>方法的声明写在了{}内

      7>在对类的成员变量声明的同时就给初始化了,请注意成员变量不能脱离对象而独立存在  

      8>方法无法像函数那样调用

      9>成员变量和方法不能用static等关键字修饰,不要跟C语言混淆

      10>类的实现可以写在main函数后面,在使用之前声明即可

      4>屏幕输出:NSLog(@“hello”);//相比C语言的printf会增加时间跟进程信息,并且会自动换行

    三、OC对象与函数

      OC对象与函数有着本质的区别:

      1>方法的实现只能写在@implementation  ... @end中,对象方法的声明只能写在@interface  ... @end内

      2>对象方法都已-开头,类方法都以+开头

      3>对象方法只能由对象来调用,类方法只能由类来调用,不能当做函数一样调用

      4>函数属于整个文件,可以写在文件中的任何位置,包括@implementation ... @end中,但写在@interface  ...@end内会无法识别,函数的声明可以在main函数的内部,也可以在main函数的外部

      5>函数调用不依赖与对象

      6>函数内部不能直接通过成员变量名访问对象的成员变量

    四、类和方法的设计

      1>工具类:基本没有任何成员变量,里面的方法基本都是类方法

      2>类方法以+开头,如+(void) run;

      3>类方法只能由类来调用

      4>调用格式:[类名 类方法名],直接在主程序中调用,无需像对象方法那样先初始化

      5>类方法的好处跟适用场合:

      不依赖与对象,执行效率更高

      能用类方法解决的问题,尽量使用类方法

      场合:当方法内部不需要使用到成员变量时,可以改为类方法

    练习题

    要求:设计一个工具类:一个计算器类,要求1>返回π  2>计算两个整数的和  3>计算某个整数的平法

     计算器类的声明

    #import <Foundation/Foundation.h>
    
    @interface Calculator : NSObject
    
    /**
     *  π的类方法
     *
     *  @return π的值
     */
    +(CGFloat) pi;
    
    /**
     *  两个整数的和的类方法
     *
     *  @param num1 第一个整数
     *  @param num2 第二个整数
     *
     *  @return 返回两个整数的和
     */
    +(NSInteger) sumOfNumber1:(NSInteger) num1 andNumber2:(NSInteger) num2;
    /**
     *  计算一个整数的平方
     *
     *  @param no 一个整数
     *
     *  @return 返回这个整数的平方
     */
    +(NSInteger) square:(NSInteger) no;
    
    @end

    计算器类的实现

    #import "Calculator.h"
    
    @implementation Calculator
    
    #pragma mark - π
    +(CGFloat) pi{
    
        return 3.14;
        
    }
    
    #pragma mark - 计算两个整数的和
    +(NSInteger) sumOfNumber1:(NSInteger) num1andNumber2:(NSInteger) num2{
    return num1+num2;
        
    }
    
    #pragma mark - 计算一个整数的平方
    +(NSInteger) square:(NSInteger) no{
        return no*no;
        
    }
    @end

    主程序:直接使用类名调用类方法

    #import <Foundation/Foundation.h>
    #import "Calculator.h"
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            /*
                //初始化并赋值
                Student * stu=[[Student alloc] init];
                stu.score=59;
                
                //调用方法
                [stu reExam];
                */
            /*
                //初始化并赋值
                Cinema * cinema=[[Cinema alloc] init];
                cinema.seatNo=50;
                cinema.leftNo=50;
                
                Ticket * ticket=[[Ticket alloc] init];
                ticket.name=@"极限挑战";
                ticket.type=@"娱乐搞笑类";
                ticket.startTime=@"20:35";
                ticket.price=65.5;
                
                //调用
                [cinema sellTickets];
                [cinema returnTickets];
                */
            
            //类方法直接用类名调用
            NSInteger result=[Calculator sumOfNumber1:5 andNumber2:6];
            NSLog(@"%ld",result);
            
            NSInteger result2=[Calculator square:6];
            NSLog(@"%ld",result2);
           
            CGFloat result3=[Calculator pi];
            NSLog(@"%g",result3);
        }
        return 0;
    }

    注意:

      1>可以允许类方法跟对象方法同名

      2>在对象方法中可以调用类方法

    五、方法名

     1>不带参数的方法

      声明: 

      

      调用:

      

      2>带参数的方法

      声明:

      

      调用:

      

      注意:冒号也是方法名的一部分

      

    六、文件编译

      在工作中,通常把不同类放到不同的文件中,每个类的声明和实现分开,声明写在.h头文件中,实现写在相应的.m文件中,类名是什么,文件名的前缀就是什么.

      假设有两个类,分别是Person类和Dog类,则通常有以下五个文件:

      1>Person.h     Person类的声明文件

      2>Person.m    Person类的实现文件

      3>Dog.h          Dog类的声明文件

      4>Dog.m         Dog类的实现文件

      5>Main.m        主函数(程序入口)

      在主函数以及类的声明文件中要使用#import包含相应的头文件

    补充:import的两个作用:一是和include一样,完全拷贝文件的内容;二是可以自动防止文件内容的重复拷贝(即使文件被多次包含,也只拷贝一份)

      在使用命令行进行编译链接文件的时候,通常把.m文件单文件编译,然后再把多有的目标文件链接,但是在Xcode中,是把所有的.m文件都进行编译链接的,若果出现重复定义的错误,那大部分的问题根源应该就是文件内容被重复包含或者是包含.m文件所引起的.

      源文件中不论是使用import还是include,都不能包含.m或者.c文件,只能放声明,因此,在OC中通常把类拆分开来,拆分成声明和实现两个部分

    提示:这也是编程思想的一种体现,可以说.h跟.m文件是完全独立的,知识为了追求更好的可读性,才要求两个文件的文件名一致,这也是把接口和实现分离,让调用者不必去关心具体的实现细节.

      Xcode的写一行编译一行,有简单的修复功能,红色是错误提示,黄色的警告信息,如果在主程序中声明了一个变量,但是这个变量没有被使用,此时也会产生警告信息,在调试程序的时候,如果发现整个页面都没报错,但是一运行就报错,那么一定死链接报错.

  • 相关阅读:
    阿里巴巴公布合伙人名单,董建华成为独董,俞永福未进入合伙人
    android cookie
    在Android的webview中定做js的alert,confirm和prompt对话框的方法
    浅谈WebView的使用 js alert
    Android的移动存储之SharedPreferences
    [android]-如何在向服务器发送request时附加已保存的cookie数据
    layout_weight
    我们是如何认识世界的
    挣钱和花钱
    时刻牢记“我是谁、为了谁、依靠谁” 始终践行党的群众观点和群众路线
  • 原文地址:https://www.cnblogs.com/my-garden/p/5427727.html
Copyright © 2020-2023  润新知