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

---------------------- 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];
}
@end

int 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值