码迷,mamicode.com
首页 > 其他好文 > 详细

黑马程序员-oc基础---oc简介、语法、思想 Foundation框架 编译链接文件的重命名 类方法 set get self

时间:2015-05-10 17:09:13      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

1.oc简介

  • C语言的基础上,增加了一层最小的面向对象语法

  • 完全兼容C语言

  • 可以在OC代码中混入C语言代码,甚至是C++代码

  • 可以使用OC开发Mac OS X平台和iOS平台的应用程序

2.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、

 

字符串以@开头  比如@"Hello"为oc的字符串   c的字符串"Hello"

 

oc程序的开发过程:

和c程序的开发过程类似

源程序.m  经过编译  生成目标文件.o    再经过链接   生成可执行文件a.out

编译cc –c main.m

链接cc main.o –framework Foundation

注意:oc程序的链接,只是把c的库函数自动链接,而oc自己的库函数,需要链接的时候写上:

        –framework Foundation,只要用了foundation框架,就得写。

       (这边你可以理解为增加 -framework Foundation 是因为该程序中使用了Foundation的框架中头文件,可以方便快速寻找该头文件)

 

编译、链接生成文件的自定义命名:

一般的编译处理,如何对编译、链接生成的目标文件、可执行文件进行重命名,主要是在对其后增加-o XXX,便重命名成为XXX

oc程序开发的编译链接的重命名如下:

    编译cc -c main.m  -o abc   //其义为生成abc的目标文件

    链接cc abc -framework Foundation -o def  //其义为生成def的可执行文件

 

下面为汇编和gcc 的编译链接的文件重命名

1) 预处理
    gcc -E test.c -o test.i
在当前目录下会多出一个预处理结果文件 test.i,打开 test.i 可以看到,在 test.c 的基础上把stdio.h和stdlib.h的内容插进去了。

2) 编译为汇编代码
    gcc -S test.i -o test.s
其中-S参数是在编译完成后退出,-o为指定文件名。

3) 汇编为目标文件
    gcc -c test.s -o test.o
.o就是目标文件。目标文件与可执行文件类似,都是机器能够识别的可执行代码,但是由于还没有链接,结构会稍有不同。

3) 链接并生成可执行文件
    gcc test.o -o test

如果有多个源文件,可以这样来编译:
    gcc -c test1.c -o test1.o
    gcc -c test2.c -o test2.o
    gcc test1.o test2.o -o test

注意:如果不指定文件名,GCC会生成名为a.out的文件,.out文件只是为了区分编译后的文件,Linux下并没有标准的可执行文件后缀名,一般可执行文件都没有后缀名。

 

编辑,编译,链接(把所有的相互关联的.o文件合并在一起,加上函数库),运行。和c类似,先编写.m文件,然后编译器编译,链接,运行。

 

OC完全兼容C语言

跟C语言一样,OC(objective-c)程序的入口依然是main函数,只不过写到一个.m文件中(文件名可以是中文)。

 1 #include <stdio.h>
 2 
 3 //oc程序的入口函数也是main函数
 4 
 5 int main(void)
 6 
 7 {
 8 
 9     printf("第一个oc程序!oc源文件完全兼容c语言!");
10 
11     return 0;
12 
13 }

编译cc –c main.m,链接cc main.o,运行./a.out

使用NSLog函数输出内容

1 #import <Foundation/NSObjCRuntime.h>
2 //不是#include,而是#import
3 int main(void)
4 {
5     //NSlog输出内容自动换行
6     NSLog(@"第二个oc程序!!");
7     return 0;
8 }

编译cc –c main.m

链接cc main.o –framework Foundation

注意:oc程序的链接,只是把c的库函数自动链接,而oc自己的库函数,需要链接的时候写上:–framework Foundation,只要用了foundation框架,就得写。

运行./a.out

NSLog与printf的区别

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

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

使用NSLog需要#import <Foundation/Foundation.h>,里面有NSLog函数的声明。

Foundation框架下的NSObjCRuntime.h头文件

不需要刻意记忆,想不起来,就编译,出错就会提示缺少什么。

可以只包含框架的主头文件,效果等价包含了这个框架里的所有的头文件。头文件在Xcode里面,路径很深,不好找。

使用printf需要#include <stdio.h>

#import的作用(预处理)

1、跟#include一样,用来拷贝某个文件的内容

2、可以自动防止文件内容被拷贝多次,也就是头文件中不用和C一样,加入下面的预处理指令了

#ifndef  xxx xxx

#define xxx xxx

#endif

 

 

Foundation框架的作用

 

开发iOS、Mac程序必备的框架,此框架中包含了很多常用的API(应用编程接口)。框架中包含了很多头文件,若想使用整个框架的内容,包含它的主头文件即可

 

#import <Foundation/Foundation.h>

 

BOOL的使用(完全可以当做整型用)

 

BOOL类型的本质:typedef signed char BOOL;

 

BOOL类型的变量只有两种取值:YES、NO

 

#define YES (BOOL)1

 

#define NO  (BOOL)0

 

BOOL的输出(当做整数来用);NSLog(@"%d %d", YES, NO);//1 0

 

C里没有布尔类型,c++里有,oc也有。不过oc的布尔和c++有区别,在C++里一切非 0 值的东西都为 true,而为0值的为false。但是Object-c里必须是1为 true ,且并被宏定义为 YES,0 为 false 并被宏定义为 NO。所以下面的代码,则肯定是得不到想要的运行顺序。

 

 1 #import <Foundation/Foundation.h>
 2 BOOL isBool(int, int);
 3 
 4 int main(void)
 5 {
 6     if (isBool(5, 1) == YES) {
 7         NSLog(@"ok");
 8     }
 9     return 0;
10 }
11 BOOL isBool(int x, int y)
12 {
13     return x - y;
14 }

 

4不是1,在oc里永远都不会等于YES(YES就是1),注意:BOOL大写,YES NO也是大写,YES就是1,NO就是0

 

多个.m文件的开发

 

跟C语言中多文件的开发是一样的,回忆c多文件开发,常量的定义或者函数的声明写在xxx.h文件,函数的定义写在xxx.c文件,主文件main.c里写主程序和函数调用,最后#include xxx.h文件,一起编译主文件main.c和xxx.c文件即可。

 

编写3个oc文件

 

main.m

 

#import "one.h"
int main()
{
    test();
    return 0;
}

 

one.h

 

void test();

 

one.m

 

#import <Foundation/Foundation.h>
void test()
{
    NSLog(@"调用了test函数");
}

 

编译:cc –c main.m test.m  (两个文件要一起编译)

 

链接:cc main.o test.o –framework Foundation

 

运行:./a.out

 

.m文件和.c文件混用开发

 

main.m

 

#import "one.h"
int main()
{
    test();
    return 0;
}

 

one.h

 

void test();

 

one.c

 

#include <stdio.h>
void test()
{
    printf("调用了test函数\n");
}

 

编译:cc –c main.m one.c

 

链接:cc main.o test.o (没有使用Foundation框架的话,就不用-framework Foundation)

 

运行:./a.out

 

面向对象的思想和面向过程的思想:

OC是面向对象的,C是面向过程的。面向对象和面向过程只是解决问题的两种不同思想

1.     面向对象和面向过程的区别

1)       以用电脑听歌为例子

a)        面向过程

  • 打开电脑
  • 播放电脑中的歌曲
  • 关闭电脑

 

b)        面向对象(不是相亲的“对象”)

  • 电脑  

²   开机  

²   播放歌曲  

²   关机

 

2)       区别分析

  • 面向过程关注的是解决问题需要哪些步骤;面向对象关注的是解决问题需要哪些对象
  • 没有开发经验很难感受到它们的区别,两种思想都能达到解决问题的目的,但是解决思路不一样

 

2.     现实生活中面向对象的例子

  • 想打电话\发短信 à 找手机,不用分析电话要怎样才能拨通
  • 去饭店吃饭 à 找服务员,不用分析怎么到厨房炒菜
  • 汽车坏了 à 找汽车维修工,不用分析修车的步骤
  • 境界:万物皆对象

 

3.     常用术语

  • 面向过程 Procedure Oriented
  • 面向对象 Object Oriented,简称OO
  • 面向对象编程 Object Oriented Programming,简称OOP

 

一、  类和对象的关系

面向对象中有2个非常重要的概念:类和对象

1.     如何创建对象

1)    面向对象解决问题的时候必须有对象,那如何创建对象呢?

 

2)    现实生活的例子:如何创造汽车对象?

a)        需要先有汽车的建造图纸,图纸上描述清楚汽车应该具备的属性和功能(行为)

  • 属性:轮子数、时速
  • 功能(行为):跑

b)        然后再根据图纸上的描述生成汽车

c)        每一辆汽车都是对象,都有自己具体的属性值,都是图纸的实例

d)       图纸是抽象的,房子是具体的。图纸是对房子对象的高度概括

 

2.     OC中的面相对象

1)    OC中的类相当于图纸,用来描述一类事物。也就是说,要想创建对象,必须先有类

2)    OC利用类来创建对象,对象是类的具体存在

3)    因此,面向对象解决问题应该是先考虑需要设计哪些类,再利用类创建多少个对象

 

3.     需要设计哪些类,如何设计类

1)    类的设计,只关心3样东西:

  • 事物名称(类名):人(Person)
  • 属性:身高(height)、年龄(age)
  • 行为(功能):跑(run)、打架(fight)

 

2)    一般名词都是类

  • 坦克发射3颗炮弹轰掉了2架飞机
  • 小明在公车上牵着一条叼着热狗的狗

3)    拥有相同(或者类似)属性和行为的对象都可以抽像出一个类

1.  愤怒的小鸟游戏界面

2.  植物大战僵尸

3. 新浪微博

4)    类名、属性、行为练习

  • 僵尸、炮弹、车、学生、书本

 

5)    哪个对象最清楚这个行为,就把这个行为写到哪个对象中去。打开电脑(开机)这个行为应该是属于电脑的。

 

一、  定义OC的类和创建OC的对象

  • 接下来就在OC中模拟现实生活中的情况,创建一辆车出来。首先要有一个车子类,然后再利用车子类创建车子对象
  • 要描述OC中的类稍微麻烦一点,分2大步骤:类的声明、类的实现(定义)。跟函数类似,函数有分声明和定义

1.     类的声明

1)       代码编写

  • 定义一个Car类,拥有2个属性:轮子数、时速,1个行为:跑
  • 类名\属性的命名规则:标示符的规则
  • 类名的命名规范:有意义、驼峰标识、首字母大写

#import <Foundation/Foundation.h>

// 类的声明

@interface Car : NSObject

{

    @public

    int wheels; // 多少个轮子

    int speed; // 时速

}

- (void)run; // 跑的行为

@end

 

2)    成员变量

  • @interface的大括号{}中声明的变量:wheels、speed
  • @interface的大括号和函数的大括号是不一样的
  • 默认会初始化为0

 

3)   @public

@public可以让Car对象的wheels和speed属性被外界访问

 

4)   NSObject

加上:NSObject的目的是让Car类具备创建对象的能力

 

2. 类的实现

// 类的实现

@implementation Car

- (void) run

{

    NSLog(@"%i个轮子,%i时速的车子跑起来了", wheels, speed);

}

@end

 

3.     创建对象

1)    代码编写

// 主函数

int main()

{

    // 创建车子对象

    Car *c = [Car new];

    c->wheels = 3;

    c->speed = 300;

   

    [c run];

    return 0;

}

 

2)  main函数的代码分析、内存分析(对象在内存中有成员)

  • [Car new]每次都会创建出新的对象,并且返回对象的地址,那么就应该用一个指针变量保存对象的地址

Car *c = [Car new];

用一个指针变量c指向内存中的Car对象   

  • 设置车子对象的属性

跟用指向结构体的指针访问结构体属性一样,用->

c->wheels = 3;

c->speed = 300;

 

 

4. 创建多个Car对象

  • 分别只设置wheels、speed属性

Car *c1 = [Car new];

c1->wheels = 4;

Car *c2 = [Car new];

c2->speed = 250;

[c1 run];

  • 1个赋值给另一个,然后修改属性

Car *c1 = [Car new];

c1->wheels = 4;

c1->speed = 250;

Car *c2 = c1;

c2->wheels = 3;

[c1 run];

 

5. 面向对象封装的好处

  • 更加接近人类的思考方式
  • 只需要关注对象,不需要关注步骤

 

6.     对象与函数参数

  • 对象成员变量作为函数参数
  • 指向对象的指针作为函数参数

u  修改指向指向对象的成员

u  修改指针的指向

 

二、  类的声明和实现

1.        @interface和@implementation的分工

 

u  @interface就好像暴露在外面的时钟表面

u  @implementation就好像隐藏在时钟内部的构造实现

 

2.        声明和定义多个类

 

3.        常见错误

l   只有类的声明,没有类的实现

l   漏了@end

l   @interface和@implementation嵌套

l   两个类的声明嵌套

l   成员变量没有写在括号里面

l   方法的声明写在了大括号里面

 

4.        语法细节

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

l   方法不能当做函数一样调用

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

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

 

5.        OC方法和函数的区别

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

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

l   C函数不能访问OC对象的成员

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

 

6.   OC的方法注意

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

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

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

 

7.        @implementation

  • 没有@interface,只有@implementation,也是能成功定义一个类的

@implementation Car : NSObject

{

    @public

    int wheels; // 多少个轮子

    int speed; // 时速

}

- (void) run

{

    NSLog(@"%i个轮子,%i时速的车子跑起来了", wheels, speed);

}

@end

  • @implementation中不能声明和@interface一样的成员变量

 

三、  方法

设计一个Caculator计算器类,它拥有计算的功能(行为)

1.        不带参数的方法

u  设计一个返回PI的方法

// 方法声明

- (double)pi;

// 方法实现

- (double)pi

{

    return 3.14;

}

 

u  方法调用

 

2.        带一个参数的方法

u  设计一个计算平方的方法

// 方法声明

- (double)square:(double)number;

// 方法实现

- (double)square:(double)number

{

    return number * number;

}

 

u  方法调用

 

 

3.        带多个参数的方法

u  设计一个计算和的方法

// 方法声明

- (double)sumOfNum1:(double)num1 andNum2:(double)num2;

// 方法实现

- (double)sumOfNum1:(double)num1 andNum2:(double)num2

{

    return num1 + num2;

}

 

u  方法调用

 

4.        方法名注意

l   冒号也是方法名的一部分

l   同一个类中不允许两个对象方法同名

 

5.        习题

给Car类设计一个方法,用来和其他车比较车速,如果本车速度快,就返回1,如果本车速度慢,就返回-1,速度相同就返回0

 

四、  匿名对象

l   属性访问

[Car  new]->speed = 200;

l   方法调用

[ [Car  new]  run];

 

一、    set方法和get方法

1.        set方法和get方法的使用场合

@public的成员可以被随意赋值,应该使用set方法和get方法来管理成员的访问(类似机场的安检、水龙头过滤,过滤掉不合理的东西),比如僵尸的生命值不能为负数

2.        set方法

1)   作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值

2)   命名规范:

  • 方法都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写
  • 形参名称不要跟成员变量同名

3.        get方法

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

2)   命名规范:get方法的名称一般就跟成员变量同名

4.        成员变量的命名规范

  • 成员变量都以下划线 _ 开头
  • 可以跟get方法的名称区分开
  • 可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量

5.        代码示例

#import <Foundation/Foundation.h>

// 声明

@interface Car : NSObject

{

    int _wheels; // 轮子个数

}

/*set方法*/

- (void) setWheels:(int)wheels;

/*get方法*/

- (int) wheels;

@end

 

@implementation Car

// set方法的实现

- (void) setWheels:(int)wheels

{

    // 对外面传进来的轮子数进行过滤

    if (wheels<=0)

    {

        wheels = 1;

    }

   

    _wheels = wheels;

}

 

// get方法的实现

- (int) wheels

{

    return _wheels;

}

@end

6.        封装的好处

  • 过滤不合理的值
  • 屏蔽内部的赋值过程
  • 让外界不必关注内部的细节

7.        练习

1>   Dog类,属性:weight、speed,方法:吃、跑

2>   Person类,属性:dog、age,方法:喂狗、遛狗

 

二、    类方法

1.     基本概念

直接可以用类名来执行的方法(类本身会在内存中占据存储空间,里面有类\对象方法列表)

2.     类方法和对象方法对比

1)   对象方法

  • 以减号-开头
  • 只能让对象调用,没有对象,这个方法根本不可能被执行
  • 对象方法能访问实例变量(成员变量)

 

2)   类方法

  • 以加号+开头
  • 只能用类名调用,对象不能调用
  • 类方法中不能访问实例变量(成员变量)
  • 使用场合:当不需要访问成员变量的时候,尽量用类方法

3)       类方法和对象方法可以同名

3.     示例

  • 设计一个方法输出类名
  • 计算器类

  

三、    self关键字

1.     成员变量和局部变量同名
  • 当成员变量和局部变量同名时,采取就近原则,访问的是局部变量
  • 用self访问成员变量,区分同名的局部变量

2.     使用细节

1)    出现的地方:所有的OC方法中(对象方法\类方法),不能出现在函数

2)    作用

  • 使用 "self->成员变量名" 访问当前方法调用的成员变量
  • 使用 "[self 方法名];" 来调用方法(对象方法\类方法)

3.     常见错误

  • 低级错误:用self去调用函数
  • 类方法中用self调用对象方法,对象方法中用self调用类方法
  • self死循环

4.     示例

  • 狗在跑之前叫两声
  • 计算器类,计算平均值的调用求和方法

 

四、    习题

  1. 设计Car类,一个对象方法跟其他车子比较车速,返回速度差,一个类方法比较两辆车的车速,返回速度差

 

 

 

 

黑马程序员-oc基础---oc简介、语法、思想 Foundation框架 编译链接文件的重命名 类方法 set get self

标签:

原文地址:http://www.cnblogs.com/cheng923181/p/4492447.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!