黑马程序员——OC语言基础篇---基本语法、类

来源:互联网 发布:mac装好的软件在哪里 编辑:程序博客网 时间:2024/05/22 14:08

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

本篇讲述了OC的基本语法以及类的使用。

基本语法篇

1.oc小知识

OC可以同时编c言和oc西,后名是.m,

可以c++西,但是要把后名改成.mm。

大部分关字以@

nil = c中的null(0)

输出使用NSLog(@"hello")(出一句之后会自动换行,所以不用'\n'),使用NSLog需要import Foundation框架的主头文件Foundation.h

#import <Foundation/Foundation.h>int main(){    NSLog(@"第一个OC小程序");    return 0;}

import用途

与include一样,拷贝文件内容,可以自动防止文件的内容被重复拷贝(相当于上一篇中所讲的条件编译在头文件里的作用)

localhost:OC liweixi$ cc 01-第一个OC程序.m  -framework Foundation

localhost:OC liweixi$ ./a.out

2015-04-15 10:53:30.814 a.out[2367:507] 第一个OC小程序

oc的开发过程


oc的程序在编译上与c言的一,但是在接的候有所不同

c言的接是将所有的.o文件和c言的函数库链接生成一个可行文件

oc编译时不会将oc的函数库链来,所以编译时需要把框架加上

2.BOOL型

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

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

#define YES (BOOL)1#define NO  (BOOL)0
BOOL的输出(当做整数来用)

NSLog(@"%d %d", YES, NO);

3. 多文件开发

OC中的多文件开发与C语言中其实是一样的,都是为开发的.m(.c)文件创建一个.h头文件,在主函数使用之前将该头文件引用进来即可(oc中最好使用import),而且.m和.c文件可以混合使用。
下面是个案例
one.m
#import "two.h"int main(){    test();    return 0;}

two.c
#include<stdio.h>void test(){    printf("这里调用了.c文件\n");}

two.h
#ifndef TWO_H#define TWO_Hvoid test();#endif
编译及运行

localhost:多文件混用 liweixi$ cc one.m two.c

localhost:多文件混用 liweixi$ ./a.out

这里调用了.c文件

localhost:多文件混用 liweixi$ 


4. 常用术语

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

类--基础篇

1. 类的设计与实现

类名:首字母大写,不要用下划线
属性
行为(功能)
完整的写一个类,必须有声明和实现 (实际上只有实现没有声明,程序也是可以运行的,但是最好还是声明和实现都要有)

//类的声明:用来声明对象的属性和行为
@interface 类名 : 父类
@end
//类的实现(方法的实现)
@implementation 类名
@end

下面通过一段代码来感受一下类吧
#import<Foundation/Foundation.h>@interface Car:NSObject{    @public    int wheels;    float speed;}- (void) run;@end@implementation Car- (void) run{    NSLog(@"车子跑起来,时速%f",speed);    }@endint main(){    Car *p = [Car new];    p->wheels = 4;    NSLog(@"车子的轮子数:%d",p->wheels);    p->speed = 200;    [p run];    return 0;}

运行结果

localhost:类相关 liweixi$ cc 03-第一个oc类的练习.m -framework Foundation

localhost:类相关 liweixi$ ./a.out

2015-04-15 11:36:01.514 a.out[2531:507] 车子的轮子数:4

2015-04-15 11:36:01.516 a.out[2531:507] 车子跑起来,时速200.000000

localhost:类相关 liweixi$ 


@public是为了能从外部访问成员变量,但是这种方法其实不推荐,面向对象的思想就是将类中所有的方法和成员变量封装,要使用成员变量只能通过方法来调用,而不能让外部知道其内部的设计,关于这点的解决方法将放到下面的set方法和get方法中来说明。
OC中方法调用都要用[对象名(类名) 方法名],上段代码中的 [p run]就是这样。另外需要补充说明的是:[Car new],Car这个类可以调用new方法,是因为它继承自NSObject,可以使用它的类方法,这个在后续的文章中再继续介绍吧。

2. OC编程的注意点

在使用类创建对象之前,会将类以及其方法加载进内存,创建的对象内默认有一个isa指针,指向该类,所以所有创建的对象都调用同一个类的方法
oc中的对象是不可能自动回收的(这个涉及到内存管理的相关知识,后面会有专门的介绍)

oc编程时的一些常见错误

(1)interface定义和implementation不可以嵌套
(2)方法的声明一定要在interface内,不可以在implementation中进行方法的声明,方法不能用static修饰
(3)interface声明的时候,不允许给成员变量赋值,不能随便将成员变量当做C语言中的变量,不能用static修饰

3. 类的合理设计

在学习过OC之后,我觉得一个程序好不好,重要在其设计,好的程序,不仅是节省内存,bug很少,更重要的是程序的拓展性好,但这对于现在的我来说,还有点遥远,所以接下来,我们通过一小段代码来感受一下类的设计。
#import<Foundation/Foundation.h>typedef struct{    int year;    int month;    int day;    }Date;typedef enum{    ColorBlue,    ColorBlack,    ColorWhite,}Color;//定义一个性别的枚举类型typedef enum{    Sex_man,    Sex_woman,    }Sex;@interface Dog:NSObject{    @public    double _weight;    Color furColor;}-(void) eat;-(void) run;@end@implementation Dog- (void) eat{    _weight+=1;    NSLog(@"狗吃完这次之后的体重是%f",_weight);}- (void) run{    _weight -= 1;    NSLog(@"狗跑完这次之后的体重是%f",_weight);}@end@interface Student:NSObject{    @public    Sex sex;    Date birthday;    double weight;    Color favColor;    char *name;    Dog *_dog;}- (void) eat;- (void) run;- (void) print;- (void) liugou;- (void) weigou;@end@implementation Student- (void) eat{    weight+=1;    NSLog(@"吃完这次之后的体重是%f",weight);}- (void) run{    weight -= 1;    NSLog(@"跑完这次之后的体重是%f",weight);}- (void) print{    NSLog(@"性别=%d,喜欢的颜色=%d,姓名=%s,生日=%d-%d-%d",sex,favColor,name,birthday.year,birthday.month,birthday.day);}- (void) liugou{    [_dog run];    NSLog(@"test%f",_dog->_weight);}- (void) weigou{    [_dog eat];}@endint main(){    Student *s = [Student new];    s -> weight = 50;    s -> sex = Sex_man;    s->birthday.year = 2011;    s->birthday.month = 9;    s->birthday.day = 10;    s->favColor = ColorBlack;    s->name = "OC-Program";    [s eat];    [s eat];    [s run];    [s run];    [s print];    Dog *d = [Dog new];    d -> _weight = 25;    d -> _furColor = ColorBlack;    s->dog = d;    [s liugou];    [s weigou];    return 0;}
运行结果

localhost:类相关 liweixi$ cc 07-类的合理设计.m  -framework Foundation

localhost:类相关 liweixi$ ./a.out

2015-04-15 12:12:55.721 a.out[2642:507] 吃完这次之后的体重是51.000000

2015-04-15 12:12:55.722 a.out[2642:507] 吃完这次之后的体重是52.000000

2015-04-15 12:12:55.723 a.out[2642:507] 跑完这次之后的体重是51.000000

2015-04-15 12:12:55.723 a.out[2642:507] 跑完这次之后的体重是50.000000

2015-04-15 12:12:55.723 a.out[2642:507] 性别=0,喜欢的颜色=1,姓名=OC-Program,生日=2011-9-10

2015-04-15 12:12:55.724 a.out[2642:507] 狗跑完这次之后的体重是24.000000

2015-04-15 12:12:55.724 a.out[2642:507] test24.000000

2015-04-15 12:12:55.724 a.out[2642:507] 狗吃完这次之后的体重是25.000000


这段代码中有两个类:Student和Dog,他们之间的关系是Student拥有Dog,是组合关系
程序中要想对狗进行操作,应该是通过调用狗自己的方法来完成,比如说:要想使狗的体重增加,对于学生来说就是喂它吃饭,对于狗来说就是吃东西,所以逻辑上来说,应该是学生通过喂狗这个动作调用狗的eat方法,最终使其体重增加。如果这段代码改成,在学生内部直接修改狗的weight变量,从程序运行上能得到同样的结果,但是从逻辑上是说不通的,狗体重的改变是其自身行为导致的,Student只是做了喂食的动作,怎么能用Student直接修改Dog的体重呢?这就是类的合理设计,必须从逻辑上来说也是合理的,而非只是保证程序结果的正确性。
0 0
原创粉丝点击