黑马程序员——6、OC语言(基本语法)

来源:互联网 发布:判断素数的条件c语言 编辑:程序博客网 时间:2024/05/02 02:46

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


一、OC的简单认识

  1. OC与C

OC是全称Object-C,是在C语言的基础上增加了一层最小的面向对象语法。

OC完全兼容C语言,可以在OC代码中混入C语言代码,甚至C++代码。

OC可以用来开发Mac OS X平台和IOS平台的应用程序。

  2. OC关键字

OC的关键字基本上都是以@开头的:

@interface、@implementation、@end

@public、@protected、@private、@selector

@try、@catch、@throw、@finally

@protocol、@optional、@required、@class

@property、@synthesize、@dynamic

self、super、id、_cmd、__block、__strong、__weak

OC中的字符串也都是@“字符串”的形式。

  3. 数据类型

基本数据类型:

C语言的基本数据类型适用于OC中,如字符型char、整型int、浮点型float/double等等

但是OC类型多了一个布尔型数据类型:BOOL(YES/NO)。

    BOOL b1 = YES;    BOOL b2 = NO;        BOOL b3 = 1; //YES    BOOL b4 = 0; //NO
</pre><h2><span style="font-family:SimHei;font-size:18px;font-weight: normal;">  4. OC的简单使用</span></h2><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"><p><span style="font-family:SimSun;font-size:12px;">(1)跟C语言一样,OC程序的入口函数依然是main函数。OC源程序被写到了一个.m文件中。</span></p></blockquote><p></p><pre name="code" class="objc">//OC程序的入口:main函数int main(){    return 0;}

(2)OC程序运行过程:

1》编写OC源程序:.m   .c

2》编译:cc -c xxx.m xxx.c

3》链接:cc xxx.o xx.o -framework Foundation(只有用到Foundation框架才需要引入)

4》运行:./a.out

(3)Foundation框架头文件的路径

1》右击Xcode.app --> 显示包内容

2》Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/System/Library/Frameworks/Foundation.framework

Xcode模板修改路径:

/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates

* File Templates文件模板:可以修改类文件等

* Project Templates 项目模板:可以修改一些项目描述

(4)Foundation框架

#import <Foundation/Foundation.h>

只需要包含Foundation框架的主头文件,就可以使用整个框架的东西。

#import的用途:

1》跟#include一样,拷贝文件的内容。

2》可以自动防止文件的内容被重复拷贝。

不需要在头文件中加入下面的预处理指令:

#ifndef  _STDIO_H_

#define _STDIO_H_

函数声明等操作  

#endif

(5)NSLog和printf的区别

1》NSLog接收OC字符串作为参数,printf接受C语言字符串作为参数。

2》NSLog输出后会自动换行,printf输出后不会自动换行。

3》使用NSLog需要#import <Foundation/Foundation.h>,使用printf需要#include <stdio.h>。

(6)布尔型BOOL

BOOL的本质:typedef signed char BOOL;

BOOL变量的取值:YES/NO

#define YES (BOOL)1

#define NO (BOOL)0

由BOOL变量的取值可以看出,BOOL变量可以当做整数1、0来使用。



二、OC的面向对象

  1. 面向对象思想

C是面向过程的,OC是面向对象的。

1》面向过程与面向对象的区别

面向过程关注的时解决问题需要哪些步骤;面向对象关注的时解决问题需要哪些对象。

2》术语

面向过程:Procedure Oriented

面向对象:Object Oriented,简称OO

面向对象编程:Object Oriented Programming ,简称OOP

  2. 类和对象

(1)类的设计

1》类名

* 类名的第一个字母必须大写

* 不能有下划线

* 多个英文单词,用驼峰标识

* 一般名词都是类

2》属性

* 拥有相同属性和行为的对象都可以抽象出一个类

3》行为(功能)

* 谁最清楚这个行为,这个行为就应该在哪个类中,该交给谁执行这个行为,由该类决定

(2)类的声明

用来声明对象的属性和行为。

成员变量和方法不能用static等关键字修饰,不能跟C语言的函数或变量混淆。

</pre><pre name="code" class="objc">#import <Foundation/Foundation.h>//: NSObject 目的是让Car这个类具备创建对象的能力@interface Car : NSObject{//大括号,用来声明对象属性    //成员变量(实例变量),默认初始化为0(成员变量不能在这里进行初始化操作)    //@public 可以让外部的指针间接访问对象内部的成员变量    @public    int wheels;    int speed;}//方法(行为)(方法也分声明和实现两步)//方法名、参数、返回值//只要是OC对象的方法,必须以减号- 开头//OC方法中,任何数据类型都必须用小括号()括住//OC方法中,小括号就一个作用:括住数据类型- (void)run;@end

</pre></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"><div><h3><span style="font-family:SimHei;font-size:14px;font-weight: normal;">(3)类的实现</span></h3></div></blockquote><div><pre name="code" class="objc">//方法的实现(说清楚方法里面的功能)@implementation Car- (void)run{    NSLog(@"车子跑起来了!");}@end

(4)创建对象

* 在使用类创建对象之前,系统会先将类加载到内存中;

* 在类中,成员变量是对象独有的,而方法是对象共有的。

    //利用类来创建对象    //在OC中,想执行一些行为,就应该写上一个中括号[行为执行者 行为名称]    // [Car new];//执行了Car这个类的new行为来创建新对象        //定义一个指针变量p,p将来指向的是Car类型的对象    //[Car new]每次都会创建一个新的对象,并且会返回新对象本身(新对象的地址)    Car *p = [Car new];    //给p所指向的对象的属性赋值    p->wheels = 4;    p->speed = 120;        Car *p2 = [Car new];    p2->wheels = 5;    p2->speed = 210;        //给p所指向的对象发送一条run消息    [p run];

(5)对象与函数

1》对象成员变量作为函数参数:是值传递,传递到函数的只是对象成员变量的值。在函数里改变这个值并不会影响外界对象的值。

2》指向对象的指针作为函数参数:是地址传递,传递到函数的是指向对象的指针。如果在函数里对这个指针指向的对象的值进行了改变,外界的对象的值也将随之改变。

void test(int w, int s){    w = 20;    s = 200;}void test2(Car *newC){    newC->wheels = 5;}void test3(Car *newC){    Car *c2 = [Car new];    c2->wheels = 5;    c2->speed = 300;    newC = c2;//指针指向变了    newC->wheels = 6;}int main(){    Car *c = [Car new];    c->wheels = 4;    c->speed = 120;        test(c->wheels, c->speed); // 值传递    test2(c); // 地址传递    test3(c); // 地址传递        return 0;}

(6)匿名对象

    //不要写类似匿名对象这样的代码,会造成内存泄露    [Car new]->speed = 300;    [[Car new] run];//每次[Car new]都会创建新对象。。

  3. 方法

(1)OC方法与函数

方法:

1》对象方法都是以减号- 开头

2》对象方法的声明必须写在@interface和@end之间,对象方法的实现必须写在@implementation和@end之间

3》对象方法只能由对象来调用

4》对象方法归类和对象所有

函数:

1》函数能写在文件的任意位置(@interface和@end除外),函数归文件所有

2》函数调用不依赖于对象

3》函数内部不能直接通过成员变量名访问某个成员变量

(2)OC方法的使用注意

* 方法只有声明,没有实现(程序崩溃:闪退(运行过程中出错) 运行错误:unrecognized selector sent to instance 0x7fdcab409690)

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

* OC在运行过程中才会检测有没有相应的方法。

* 编译的时候:如果访问了不存在的成员变量则直接报错;如果访问了不存在的方法,仅仅只是警告。

* 冒号也是方法名的一部分。

* 同一个类中不允许有两个对象方法同名。

#import <Foundation/Foundation.h>@interface JiSuanQi : NSObject//方法名:pi- (double)pi;//OC方法中,一个参数对应一个冒号//方法名:pingFang:(冒号也是方法名的一部分)- (int)pingFang:(int)num;//- (int)sum:(int)num1 :(int)num2;//方法名:sumWithNum1:andNum2:- (int)sumWithNum1:(int)num1 andNum2:(int)num2;//- (int)sumWithNum1:(int)num1 andNum2:(int)num2 andNum3:(int)num3;@end@implementation JiSuanQi- (double)pi{    return 3.14;}- (int)pingFang:(int)num{    return num*num;}//- (int)sum:(int)num1 :(int)num2- (int)sumWithNum1:(int)num1 andNum2:(int)num2{    return num1+num2;}@end

(3)方法的分类

类方法和对象方法可以同名。

1》类方法

格式:[类名 方法名];

* 以加号+ 开头;

* 只能用类名调用,对象不能调用;

* 类方法中不能访问实例变量(成员变量);

好处:不依赖于对象,执行效率高。

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

2》对象方法

格式:[对象名 方法名];

* 以减号- 开头;

* 只能让对象调用,没有对象,这个方法就不可能被执行;

* 对象方法能访问实例变量(成员变量)。

#import <Foundation/Foundation.h>@interface Person : NSObject{    int age;}+ (void)printClassName;- (void)test;+ (void)test;@end@implementation Person+ (void)printClassName{    //实例变量age不能再类方法中访问    //NSLog(@"this class call Person = %d", age);    NSLog(@"this class call Person");}- (void)test{    NSLog(@"test对象方法");    [Person test];}+ (void)test{    NSLog(@"test类方法");    //死循环    //[Person test];}@endint main(){    //用对象调用类方法,运行报错,不能识别。。    Person *p = [Person new];    [p test];        [Person test];    [Person printClassName];        return 0;}

(4)setter方法和getter方法

一般为了防止使用@public对对象的成员随意赋值,我们使用setter方法和getter方法来管理成员的访问。

1》setter方法

* 作用:给外界提供一个方法用来设置成员变量,可以在方法里面过滤掉一些不合理的值

* 命名规范:

  方法都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写;

  返回值一定是void,一定要接受一个参数,而且参数类型跟成员变量类型一致;

  形参名称不要跟成员变量同名。

2》getter方法

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

* 命名规范:

  肯定有返回值,而且类型跟成员变量一致;

  不需要接收任何参数;

  getter方法的名称一般就跟成员变量同名。

3》成员变量的命名规范

* 成员变量都以下划线_ 开头;

* 可以跟get方法的名称区分开;

* 可以跟其他局部变量区分开,一看到下划线开头的变量,一般都是成员变量。

  4. self关键字

当成员变量和局部变量同名时,系统就会采取就近原则,访问局部变量,而不是访问成员变量。这时,我们可以用self访问成员变量,区分同名的局部变量。

概念:谁调用了当前方法,self就代表谁(方法调用者)

* self出现在对象方法中,self代表对象

* self出现在类方法中,self代表类

格式:

1》self->成员变量名:访问当前方法调用的成员变量

2》[self 方法名]:调用方法(对象方法或类方法)

使用场合:所有的OC方法中,包括对象方法和类方法,不能出现在函数中。

-(void)test{    // self死循环【注意】    //self是个指针,指向方法调用者,代表当前对象    [self test]; }



三、OC面向对象的三大特征

  1. 封装

* readonly:只读,只提供getter方法就行。

* 成员变量:一定要以下划线_ 开头

  作用:让成员变量与get方法名区分开;可以跟局部变量区分开。

  成员变量尽量不要用@public,以便更好地实现封装。

封装的好处:

1》更加接近人类的思考方式,只需要关注对象和行为,不需要关注具体实现步骤。

2》过滤不合理的值,屏蔽内部的处理过程,让外界不需要关注内容的细节。

* 直接调用父类中的某个方法。

* super处在对象方法中,那么就会调用父类的对象方法;super处在类方法中,那么就会调用父类的类方法。

* 使用场合:子类重写父类的方法时,想保留父类的某些做法。

  2. 继承

* 将具有相同属性和行为的类,抽取出一个父类;

* 子类在父类的基础上,再扩充属性和方法;

* 子类的方法和属性的访问过程:先去子类里面找,如果子类没有,再去父类里面找;

* 父类被继承了,但是还是可以照常使用这个类;

* 全部OC类的最终父类是NSObject。

专业术语:父类/超类 superclass、子类 subclass/subclasses

(1)继承的好处和坏处

好处:不改变原来模型的基础上,扩充方法;建立了类与类之间的联系;抽取了公共的代码,减少代码编写;子类可以拥有父类的所有成员变量和方法。

坏处:耦合性强,类之间的关系太紧密(改一类而动很多类)。

(2)继承的使用场合

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

* 当A类完全拥有B类中部分属性和方法时,可以考虑让B类继承A类,或考虑B类组合A类。

(3)继承的注意事项

* 继承是单继承,不能继承自多个类;

* 父类必须声明在子类前面;

* 子类和父类不能有相同的成员变量;

* 子类可以重写父类的方法,调用某个对象的方法时,优先区当前对象的类中寻找,之后才会往父类方向找。

(4)super

格式:[super 方法名];

super的作用:

(5)继承和组合

继承:xxx 是 xx

组合:xxx 拥有 xx

#import <Foundation/Foundation.h>/*************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/*************Dog实现****************/@implementation Dog@end/*************Cat声明****************/@interface Cat : Animal@end/*************Cat实现****************/@implementation Cat@end

  3. 多态

概念:某一类事物的多种形态。

(1)多态的实现

* 没有继承就没有多态。

* 子类对象赋值给父类的指针,然后用父类指针就可以访问子类对象的属性和方法了。

* 多态是动态绑定,即在运行时,根据对象的具体类型来确定动态调用的方法是哪个子类(或父类本身)的方法。

(2)多态的好处和坏处

好处:如果函数、方法参数中使用的时父类类型的,可以传入父类、子类对象。

坏处:不能访问子类的属性(成员变量),不能调用子类特有的方法(子类有父类没有的方法)(除非强制类型转换)

#import <Foundation/Foundation.h>//Animal@interface Animal : NSObject- (void)eat;@end@implementation Animal- (void)eat{    NSLog(@"Animal eating..");}@end//Dog@interface Dog : Animal- (void)run;@end@implementation Dog- (void)eat{    NSLog(@"Dog eating..");}- (void)run{    NSLog(@"Dog running");}@end//Cat@interface Cat : Animal@end@implementation Cat- (void)eat{    NSLog(@"Cat eating..");}@end//如果形参中使用的时父类类型,可以传入父类对象、子类对象void feed(Animal *a){    [a eat];}int main(){    /*    //多种形态    Dog *d = [Dog new]; //Dog类型        //多态:父类指针指向子类    Animal *a = [Dog new];        [a eat]; //调用方法时 会检测对象的真实形象    //    只是警告,弱语法//    Cat *c = [Animal new];//    NSSring *s = [Cat new];     */        Dog *d = [Dog new];    feed(d);    Cat *c = [Cat new];    feed(c);        //多态的局限性:父类类型的指针变量,不能用来调用子类的方法 [aa run];    //虽然只是警告(编译器),运行时动态检测(所以运行通过)    Animal *aa = [Dog new];    //[aa run]; // 错误    Dog *dd = (Dog *)aa; //强制转换就好了,(Dog *)类型转换是给编译器看的    [dd run]; // 正确        return 0;}


0 0
原创粉丝点击