一、类的声明和实现
1.类的声明:声明对象的属性、行为
@interface Car : NSobject
@end
注意点:Car为类名,类名的第一个字母必须是大写;
不能有下划线;
多个英文单词,用驼峰标识。
:是继承父类。
NSobject是基类,继承基类的类具有创建对象的能力。
2.类的实现:
@implement Car
@end
具体举例:
#import <Foundation/Foundation.h>
// 类的声明
@interface Car : NSObject
{
@public
int wheels; // 多少个轮子
int speed; // 时速
}
- (void)run; // 跑的行为
@end
成员变量
@interface的大括号{}中声明的变量:wheels、speed
@interface的大括号和函数的大括号是不一样的
默认会初始化为0
@public
@public可以让Car对象的wheels和speed属性被外界访问
// 类的实现
@implementation Car
- (void) run
{
NSLog(@"%i个轮子,%i时速的车子跑起来了", wheels, speed);
}
@end
二、创建对象
//主函数
int main()
{
//创建车子对象
Car *c = [Car new];
//在OC中,想执行一些行为,就写上一个括号
// [行为执行者 行为名称]
[c run];
return 0;
}
创建多个对象
Car *c1 = [Car new];
Car *c2 = [Car new];
注:每次调用new方法创建一个对象,都会在内存中开辟一个新的存储空间。
若把1个对象赋值给另一个对象:
Car *c1 = [Car new];
c1->wheels = 4;
Car *c2 = c1;
c2->wheels = 3;
这里c1 的值没有改变。
三、面向对像封装的好处
更加接近人类的思考方式;
只需要关注对象,不需要关注步骤。
对成员变量进行封装,不允许外面随意修改、访问成员变量的值。
封装:set 方法
1.作用:提供一个方法给外界设置成员变量值
2.命名规范:
(1)方法名必须以set开头
(2)set 后面跟上成员变量的名称,成员变量的首字母必须大写
(3)返回值一定是void
(4)一定要接受一个参数,而且参数类型跟成员变量类型一致
(5)形参名称不能跟成员便量名一样
例如:- (void)setAge:(int)newAge;
get 方法:
1.作用:返回对象内部的成员变量;
2.命名规范:
(1) 肯定有返回值,返回值类型肯定与成员变量类型一致;
(2) 方法名跟成员变量名一样;
(3) 不需要接收任何参数
例如: - (int)age;
注:为了和方法名还有局部变量区分开来,
成员变量的命名规范:一定要一 __ 下划线开头。
·
四、对象与函数参数
将对象作为参数传入函数,函数参数也指向了该对象;
要注意函数参数之后有没有改变指向,是不是一直指向传入的对象的。
五、常见错误
1.只有类的声明,没有类的实现;
2.漏了@end;
3.@interface 和 @implementation嵌套;
4.两个类的声明嵌套;
5.成员变量没有写在括号里面;
6.方法的声明卸载了{}里面。
六、语法细节
1.成员变量不能在{}中进行初始化、不能被直接拿出去访问;
2.方法不能当做函数一样调用;
3.成员变量\方法不能用static等关键字修饰,别跟 C语言混在一起;
4.类的实现可用在main函数的后面,主要在声明后面就行了。
七、oc方法与函数的区别
1.对象方法都是以减号 - 开头
2.对象方法的声明必须写在@interface和@end 之间
对象方法的实现必须写在@implementation和@end之间
3.对象的方法只能对象来调用
函数
1.函数能写在文件中的任何位置(@interface 和@end之间),函数归文件所有
2.函数调用不依赖于对象
3.函数内部不能直接通过成员变量名来访问对象的成员变量
4.低级错误:方法有声明,但是实现的时候写成了函数
注:oc方法注意
1.方法只有声明,没有实现(经典错误);
2.方法没有声明,只有实现(编译器警告,但是能调用,oc的弱语法);
3.编译的时候:访问没有的成员变量直接报错,访问没有的方法,只是警告;
八、匿名对象
理解:没有定义一个指针指向新创建的对象,该对象即匿名对象。
使用注意:每次写 [类名 new],都意味着新创建了一个对象,不要以为是一个对象进行操作。
所以,尽量不要使用匿名对象。
九、小练习
方法的声明和实现:
/*
计算器类
方法:
1.返回π
2.计算某个数的平方
3.计算两个整数的和
*/
#import <Foundation/Foundation.h>
//OC中不允许方法名重复
@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;
@end
@implementation JiSuanQi
- (double)pi
{
return 3.14;
}
- (int)pingfang:(int)num
{
return num*num;
}
/*
- (int)sum:(int)num1 :(int)num2
{
return num1+num2;
}
*/
- (int)sumWithNum1:(int)num1 andNum2:(int)num2
{
return num1+num2;
}
@end
int main()
{
JiSuanQi *jsq=[JiSuanQi new];
int a=[jsq pi];
NSLog(@"π的值是:",a);
int c=[jsq pingfang:10];
NSLog(@"该数字的平方是:",c);
int s=[jsq sumWithNum1:10 andNum2:5];
return 0;
}
比车速:
/*
设计一个方法,用来和其他车比较速度,返回车速的差距
*/
#import <Foundation/Foundation.h>
@interface Car : NSobject
{
@public
int speed;//车速
//与其他车子比较速度
- (int)compareSpeedWithOther:(Car *)other;
@end
@implementation Car
- (int)compareSpeedWithOther:(Car *)other
{
//speed当前这辆车和other这辆车的速度差距
//other->speed
//返回
return speed - other->speed;
}
@end
int main()
{
//创建一个新对象c1
Car *c1=[Car new];
c1->speed=50;
//创建另一个对象c1
Car *c2 = [Car new];
c2->speed = 40;
int a = [c1 compareSpeedWithOther:c2];
NSLog(@"a=%d",a);
return 0;
}
运行结果:a = 10
成员变量:
/*
人
类名:Person
属性:(成员变量\实例变量):体重、年龄
行为(方法):走路
*/
/*
1.类的声明
* 成员变量
*方法的声明
*/
#import <Foundation/Foundation.h>
@interface 类名: NSobject
{o
@public
int age;
double weight;
}
//方法的声明;
- (void)walk;
- (void)eat;
@end
//2.类的实现
@implementation 类名
//实现@interface中声明的方法
- (void)walk
{
NSLog(@"%d岁、%f公斤的人走了一段路",age,weight);
}
- (void)eat
{
NSLog(@"%d岁、%f公斤的人在吃东西",age,weight);
}
@end
int main()
{
//在使用类创建对像前,会将类加载进内存,只加载这一次,每个对象都有一个默认的内部指针,指向这个类
Person *p=[Person new];
p->age=20;
p->weight=40.0;
[p eat];//20 , 40.0的人在吃东西
Person p2=[Person new];
p2->age=30;
p2->weight=50.0;
p=p2;
p->age=40;
[p2 walk];//40 , 50.0的人在走路
/*
Person p=[Person new];
p->age=20;
p->weight=40.0;
[p walk];//20 , 40.0的人在走路
Person p2=[Person new];
p2->age=20;
p2->weight=50.0;
[p2 walk];//20 , 50.0的人在走路
*/
return 0;
}
匿名对象:
/*
匿名对象
*/
#import <Foundation/Foundation.h>
@interface Car : NSobjec
{
@public
int speed;//车速
}
- (void)run;
@end
@implementation Car
- (void)run
{
NSLog(@"%d速度的车子跑起来了",speed);
}
@end
int main()
{
/*
Car *c=[Car new];
c->speed=50;
[c run];
*/
//不要写类似匿名对象这样的代码
//只要求能够看懂代码
[Car new]->speed=300;
Car
[[Car new] run];//输出结果为0 ;以为每次[Car new]都是创建了一个新的对象
}
对象和函数:
#import <Foundation/Foundation.h>
@interface Car : NSobject
{//成员变量
@public
int wheels;
int speed;
}
- (void)run;
@end
@implementation Car
- (void)run
{
NSLog(@"%d个轮子,速度为%dkm/h的车子跑起来了",wheels,speed );
}
@end
void test(int w,int s)
{
w=2;
s=30;
}
void test1(Car *newC)
{
newC-wheels=4;
}
void test2(Car *newC)
{
Car *c=[Car new];
c-wheels=5;
c->speed=50;
newC=c;
newC->wheels=6;
}
int main()
{
Car *p=[Car new];
p->wheels=3;
p->speed=40;
//test(p->wheels,p->speed);值传递
//[p run]; 结果是:, 40
//tesst1(p); newC和p指针指向了同一个内存空间
//[p run]; 结果是:, 40
test2(p);//newC指针开始与p指针指向同一个空间,后来指向了c指针指向的内存空间,所做的操作与p指针指向的空间无关
[p run];//3 , 40
return 0;
}
对象与函数参数:
/*
对象与函数参数
*/
#import <Foundation/Foundation.h>
@interface Car : NSobject
{
//成员变量
int wheels;
int speed;
}
- (void)run;
@end
@implementation Car
- (void)run
{
NSLog(@"车子的速度是%dkm/h ",speed);
}
@end
void test(int w,int s) //基本数据类型都是值传递
{
w = 3;
s = 30;
}
void test2(Car *newC)
{
newC->speed = 30;
}
void test3(Car *newC)
{
Car *c2 = [Car new];
c2->speed = 50;
c2->wheels = 2;
newC = c2; // newC指向了C2指向的对象,不再指向传入的实参对象
newC->speed = 30;
}
int main()
{ //新建一个对象
Car *c1 = [Car new];
c->wheels = 4;
c->speed = 40;
/*[c run];// speed = 40;
test(c->wheels,c->speed);
[c run]; //speed = 40;
test2(c);
[c run];//speed = 30;newC也指向了传入的对象 */
test3(c);
[c run];//speed = 40;
return 0;
}