第一部分 基本语法
一、与C语言的区别
1、Objective-C是在C语言的基础上添加了面向对象的语法,可以完全兼容C语言语法,源文件为.m文件,在编写代码的时候可以混入C语言。
2、语法预览:
#import
int main()
{
NSLog(@"第2个OC程序!!!");
return 0;
}
(1)#import的用途:
1> 跟#include一样,拷贝文件的内容。
2> 可以自动防止文件的内容被重复拷贝。
(2)Foundation/Foundation.h:第一个Foundation代表框架,第二个是这个框架下的主头文件。
1> 主头文件路径:点击Xcode.app --> 显示包内容 /Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKS/iPhoneOS8.2.sdk/System/Library/Frameworks/Foundation.framework
2> 主头文件:最主要的头文件,名字一般跟框架名称一样,包含了框架中的所有其他头文件。
3> 只需要包含Foundation框架主头文件,就可以使用整个框架的东西。
(3)NSLog(@"第二个OC程序");
1> NSLog和printf作用是一样的,但是不一样的是,NSLog输出会自动换行。
2> 字符串前面需要加@。
(4)运行过程
1> 编写OC源文件:.m .c
2> 编译:cc -c xxx.m xxx.c
3> 链接:cc xxx.o xxx.o -framework Foundation
(只有用到了Foundation框架才需要加上 -framework Foundation)
补充:编译链接可以一步完成:cc xxx.m/xxx.c -framework Foundation
4> 运行:./a.out
(5)多文件开发和C语言中的多文件开发一样,文件可以OC和C混用,只要对应着使用#include 和#import 。
(6)基础数据类型:BOOL类型
1> BOLL类型的输出当做整数来输出
BOOL b = YES;
NSLog(@"b=%d", b); // b=1
2> BOOL类型的本质:
typedef signed char BOOL;
#define YES (BOOL)1
#define NO (BOOL)0
第二部分 类与对象
一、概述
1、OC是面向对象的,C语言是面向过程的,解决问题的思路不一样。
2、区别:
(1)面向过程,关注的是怎么做。
(2)面向对象,关注的是用谁做。
3、现实中的例子:
(1)想打电话,找手机,不用分析电话要怎样才能拨通
(2)去饭店吃饭,找服务员,不用分析怎么到厨房炒菜
(3)汽车坏了,找汽车维修工,不用分析修车的步骤
(4)
万物都是对象!!!
二、类与对象概述
1、OC是面向对象的,解决问题靠的是对象,那么对象怎么创建呢?
2、OC中的类就类似于现实生活中的图纸,对象就类似于图纸上的产品,如果想要制造产品,需要先设计图纸。同样的,如果想要创建对象,需要先设计类。
三、类的设计:
1、类名
(1)类名的第一个字母必须是大写
(2)不能有下划线
(3)多个英文单词,用驼峰标识
2、属性
3、方法(行为)
4、实例:
/*
类名:Car
属性(成员变量\实例变量):轮胎个数、时速(速度)
方法(行为):跑
*/
#import
// 1.类的声明
@interface Car : NSObject
{
@public
int wheels;
int speed;
}
- (void)run;
@end
// 2.类的实现
@implementation Car
- (void)run
{
NSLog(@"%d个轮子、速度为%dkm/h的车子跑起来了", wheels, speed);
}
@end
(1)类的声明
1> 其中@interface 类名 : NSObject和@end是固定格式,在它们之间声明成员变量以及声明方法。
2> NSObject的作用:让类具备创建对象的能力。
3> 大括号内的声明是成员变量/实例变量,默认的初始化为0。
4> 在成员变量的上面,写@public,它的作用是让后续创建的外部指针间接访问对象内部的成员变量。
5> 在大括号外面,@end前面声明方法,必须以-开头,有返回值类型、方法名和形参。只要出现数据类型,就必须用小括号()括住。
(2)类的实现
1> @implementation 类名和@end也是固定格式。
2> 用来实现@interface中声明的方法。和函数是非常相似的,有声明有定义。
(3)使用注意
1> 类的声明和实现不能嵌套
2> 类的声明必须写在@interface和@end中,并且不能出现在成员变量的大括号{}中
3> 类的实现必须写在@implementation和@end中
4> 成员变量中不允许初始化,也不允许出现相同的成员变量,不能随便将成员变量当做C语言中的变量来使用(不能使用static)。
5> 类也有作用域,在使用类之前,必须有类的声明。类的实现可以放在使用之后。
6> 只有类的声明,没有类的实现是会报错的,而有类的实现,没有类的声明确能成功定义一个类。
四、创建对象
1、经过上面的代码,我们已经设计好了一个叫Car的类,那么我们就根据它来创建对象。
2、实例
int main()
{
Car *c = [Car new];
// 对c指向的对象中的成员变量赋值
c->wheels = 4;
c->speed = 250;
[c run];
return 0;
}
(1)在OC中,[Car new]表示利用Car类创建了一个新的对象。[Car new]
每次都会创建出一个新对象,并且会返回新对象本身(新对象地址)。把这个地址赋值给指针变量c,c指向的是Car类型的对象。
(2)对象会按照上面我们声明的方式创建成功,对象内部会成员变量,并且每个对象中都默认的会有一个isa指针,这个指针会指向对象所对应的类,而类里面放着方法列表的声明。
(3)[c run]具体含义:给指针变量c所指向的对象发送run消息,调用当前对象中的方法run,对象会顺着isa指针找到所对应的类,在类中找到run之后,执行run的代码,run实现中涉及到的成员变量需要回c指向的对象中访问。
3、匿名对象
int main()
{
Car *c = [Car new];
c->speed = 250;
[c run];
// 匿名对象
[Car new]->speed = 300;
[[Car new] run]; // 因为[Car new]会每次创建新对象,并且默认把成员变量赋值为0,所以调用方法,输出结果一定会是0
return 0;
}
五、OC对象和函数
int main()
{
Car *c = [Car new];
c->wheels = 4;
c->speed = 250;
test(c->wheels, c->speed);
//test1(c);
//test2(c);
[c run];
return 0;
}
1、把对象的成员变量当做形参传递给函数
void test(int w, int s)
{
w = 20;
s = 200;
}
结果:4个轮子、速度为250km/h的车子跑起来了
分析:值传递,改变函数内部形参,不会改变外部实参。
2、把指向对象的指针作为形参传递给函数
void test1(Car *newC)
{
newC->wheels = 5;
}
结果:5个轮子、速度为250km/h的车子跑起来了
分析:指针c传递给函数形参,相当于把c赋值给了newC,那么newC也指向了对象,通过newC->wheel = 5重新给对象中的成员变量赋值了。
3、把指向对象的指针作为形参传递给函数
void test2(Car *newC)
{
Car *c2 = [Car new];
c2->wheels = 5;
c2->speed = 300;
newC = c2;
newC->wheels = 6;
}
结果:4个轮子、速度为250km/h的车子跑起来了
分析:指针c传递给函数形参,相当于把c赋值给了newC,那么newC也指向了对象,函数内新创建了一个指针变量c2指向的对象,又把c2赋值给了newC,那么newC就指向着c2指向的那个对象,newC->wheels = 6改变的是函数内对象的成员变量,第一个对象没有做任何改变。
4、使用注意
(1)函数能写在文件中的任意位置(@interface和@end之间除外),函数归文件所有
(2)函数调用不依赖于对象
(3)函数内部不能直接通过成员变量名访问某个对象的成员变量
(4)方法只能由对象来调用,不能当做函数来调用,并且方法归类\对象所有
六、方法
#import
@interface JiSuanQi : NSObject
// 方法名:pi
- (double)pi;
// 方法名:pingFang:
- (int)pingFang:(int)num;
// 方法名:sumWithNum1:andNum2:
- (int)sumWithNum1:(int)num1 andNum2:(int)num2;
@end
@implementation JiSuanQi
- (double)pi
{
return 3.14;
}
- (int)pingFang:(int)num;
{
return num * num;
}
- (int)sumWithNum1:(int)num1 andNum2:(int)num2
{
return num1 + num2;
}
@end
int main()
{
JiSuanQi *jsq = [JiSuanQi new];
return 0;
}
1、不带参数的方法
- (double)pi
{
return 3.14;
}
调用方法
2、带参数的方法
- (int)pingFang:(int)num;
{
return num * num;
}
调用方法
[指针变量名 方法名:实参];
[jsq pingFang:10];
3、带多个参数的方法
- (int)sumWithNum1:(int)num1 andNum2:(int)num2
{
return num1 + num2;
}
调用方法
[指针变量名 方法名:实参1 方法名:实参2];
[jsq sumWithNum1:20 andNum2:5];
4、使用注意
OC方法中,一个参数对应一个冒号,冒号前面需要有详细的描述信息
5、课后练习
/*
1.设计一个”狗“类
1> 属性
* 颜色
* 速度(单位是m/s)
* 性别
* 体重(单位是kg)
2> 行为
* 吃:每吃一次,体重增加0.5kg,输出吃完后的体重
* 吠(叫):输出所有的属性
* 跑:每吃一次,体重减少0.5kg,输出速度和跑完后的体重
* 比较颜色:跟别的狗比较颜色,如果一样,返回YES,不一样,返回NO
* 比较速度:跟别的狗比较速度,返回速度差(自己的速度 - 其他狗的速度)
*/
#import
// 狗的颜色
typedef enum {
ColorGreen,
ColorBlack,
ColorRed
} Color;
// 狗的性别
typedef enum {
SexMale,
SexFlmale
} Sex;
// 1.类的声明
@interface Dog : NSObject
{
@public
Color dogColor; //颜色
int speed; //速度m/s
Sex xingBie; //性别
double weight; //体重kg
}
- (void)eat; //吃
- (void)fei; //吠
- (void)run; //跑
- (BOOL)biJiaoCloarWithOther:(Dog *)other; //比较颜色
- (int)biJiaoSpeedWithOther:(Dog *)other; //比较速度
@end
// 2.类的实现
@implementation Dog
- (void)eat //吃
{
weight += 0.5;
NSLog(@"吃完这次,狗的体重是%fkg", weight);
}
- (void)fei //吠
{
NSLog(@"狗的颜色=%d,狗的速度=%d,狗的性别=%d,狗的体重=%f",
dogColor, speed, xingBie, weight);
}
- (void)run //跑
{
weight -= 0.5;
NSLog(@"速度是%dm/s,跑完这次,狗的体重是%fkg", speed, weight);
}
- (BOOL)biJiaoCloarWithOther:(Dog *)other //比较颜色
{
return dogColor == other->dogColor;
}
- (int)biJiaoSpeedWithOther:(Dog *)other //比较速度
{
return speed - other->speed;
}
@end