您的位置:首页 > 职场人生

黑马程序员-IOS-OC基础-面向对象语法一

2014-04-06 19:41 441 查看
-------------------------------------- android培训java培训ios培训期待与您交流!
---------------------------------

面向对象的思想

1,OC语言是面向对象的,C语言是面向过程的。面向对象和面向过程只是解决问题的两种不同的思想。其实面向对象的思想就是指挥对象做事情,你自己不需要知道知道过程,只要知道结果就行了。两者的区别:面向过程关注的是解决问题需要哪些步骤;面向对象关注的是解决问题需要哪些对象。
2,常用的术语:
面向过程 Procedure Oriented
面向对象 Object Oriented 简称 OO
面向对象编程 Object Oriented Programming 简称 OOP

类和对象

在面向对象中有两个非常重要的概念:类和对象(类就像图纸,对象就像是根据图纸创建出来的实物。)
1,类的设计
<1>,类名的第一个字母必须是大写。
<2>,类名中不能有下划线。
<3>,类名由多个英文单词组成时,要用驼峰标识。
2,类的声明与实现(可以声明和定义多个类)



@interface就像暴露在外面的时钟表面;@implementation就好像隐藏在时钟内部的构造实现。
没有@interface,只有@implemetation也可以开发一个类(但不常用)。
<1>,类的声明用关键字@interface 类名 : NSObject { 声明类的成员变量;} @end
<2>,类的实现用关键字@implemetation 类名 @end
<3>,常见错误
1,只有类的声明,没有类的实现。
2,漏掉了@end
3,@interface和@implementation嵌套。
4,两个类的声明嵌套。
5,成员变量没有写在大括号里面。
6,方法的声明写在了大括号内。
<4>,语法细节
1,成员变量不能在{ }中初始不能被外面直接拿去访问。
2,方法不能当做函数一样调用。
3,成员变量\方法不能用static等关键字修饰。
4,类的实现可以写在main函数的后面,只要在类的声明后面就行。
<5>,OC方法和函数的区别
1,OC方法只能声明在@interface和@end之间,只能实现在@implementation和@end之间,也就是说OC的方法不能离开类独立存在。
2,C函数不属于类,跟类没有联系,C函数只归定义函数的文件所有。也就是函数的等级比OC方法的等级高。
3,C函数不能访问OC对象的成员。
4,低级错误:方法有声明,但是实现的时候写成了函数。
<6>,OC的方法注意
1,方法只有声明,没有实现(经典错误)。
2,方法没有声明,只有实现(编译器会警告,但是能调用,这是OC的弱语法)。
3,编译的时候:访问没有的成员变量直接报错,访问没有的方法,只是警告。
3,方法
<1>不带参数的方法


不带参数方法的调用



<2>,带参数的方法



带参数的方法的调用



<3>,多参数方法



多参数的方法的调用



<4>,方法名注意点
(1),冒号:也是方法名的一部分。
(2),同一类中不允许两个对象方法同名。
3,创建对象 [类名 new]; 匿名对象调用方法:[
[Person new] eat ]
练习
/*
类名:人(Person)
属性:名字、年龄
行为:吃饭
*/
//导入Foundation框架的头文件
#import <Foundation/Foundation.h>
//声明Preson类
// : NSObjet 的目的是:让Person这个类具备创建对象的能力(new方法)
@interface Person : NSObject
{
//声明类的属性(成员变量),成员变量的值默认初始化为0
@public//@public可以让成员变量被外界访问
//成员变量尽量以下划线_开头。
NSString *_name;//名字 默认初始化值为空(nil)  NSString 是OC字符串
int _age;   //年龄 默认初始化值为0
}
//声明方法(行为)只要是OC对象的方法,必须以减号-开头
- (void)eat;
@end    //类的声明结束

//类的实现
@implementation Person
//实现方法(说清楚方法里面有什么代码)
- (void) eat
{
NSLog(@"名字叫%@,年龄为%d的人在吃饭",_name,_age);
}
@end    //类的实现结束

//主函数
int main()
{
//在OC中,想执行一些行为,就写上一个中括号[行为执行者 行为名称]
//利用类创建对象
//执行了Person这个类的new行为来创建对象
Person *p = [Person new];//[Person new]每次都会创建出新的对象,并且返回对象的地址,那么就应该用一个指针变量来保存对象的地址。
//设置Person对象的属性值
p -> _name = @"张三";//这里的@代表的是OC字符串
p -> _age = 25;
//给p所指向的对象发送一条eat消息,也就是调用Person对象的eat方法。
[p eat];
return 0;
//运行结果是:名字叫张三,年龄为25的人在吃饭
}


面向对象的三大特性

面向对象的三大特性:封装、继承、多态
1,封装
<1>封装的好处:
1,过滤不合理的值。2,屏蔽内部的赋值过程。3,让外界不必关注内部的细节。
//封装
#import <Foundation/Foundation.h>

@interface Student : NSObject
{
/*
成员变量得到命名规范:一定要以下划线 _开头
作用是:
1,让成员变量和get方法的名称区分开;
2,可以跟局部变量区分开,
*/
//@public   //成员变量尽量不要用@public
int _age;

}
/*set方法
1,作用:提供一个方法给外界设置成员变量值
2.命名规范:
1>,方法名必须以set开头
2>,set后面跟上成员变量的名称,成员变量的字母必须大写(setAge)
3>,返回值一定是void
4>,一定要接收一个参数,而且参数类型跟成员变量类型一致
5>,形参的名称不能跟成员变量名一样
*/
//声明set方法
- (void)setAge:(int)age;
/*
get方法
1,作用:返回对象内部的成员变量。
2,命名规范:
1>,肯定有返回值,返回值类型与成员变量类型一致
2>,方法名跟成员变量名一致
3>,不需要接收任何参数
*/
//声明get方法
- (int)age;
//声明study方法
- (void)study;
@end

@implementation Student
//实现set方法
- (void)setAge:(int)age
{
//对传进来的参数进过滤
if (age <= 0)
{
age = 1;
}
_age = age;
}
//实现get方法
- (int)age
{
return _age;
}
//实现study方法
- (void)study
{

NSLog(@"%d岁的学生在学习",_age);
}
@end

int main()
{
//创建Student类对象
Student *stu = [Student new];
//stu ->_age = 10; //成员变量加@public才可以这样做,但是尽量不要这样。
[stu setAge:25];
[stu study];
NSLog(@"学生的年龄%d",[stu age]);
return 0;
}
练习
#import <Foundation/Foundation.h>

@interface Dog : NSObject
{
//定义成员变量
double _weight;
double _speed;

}
//声明成员变量的set和get方法
- (void)setWeight:(double)weight;
- (double)weight;

- (void)setSpeed:(double)speed;
- (double)speed;
//声明eat和run方法
- (void)eat;
- (void)run;
@end

@implementation Dog
//成员变量的set方法的实现
- (void)setWeight:(double)weight
{
_weight = weight;
}
//成员变量get方法的实现
- (double)weight
{

return _weight;
}
//成员变量的set方法的实现
- (void)setSpeed:(double)speed
{

_speed = speed;

}
//成员变量get方法的实现
- (double)speed
{
return _speed;
}
//实现eat方法
- (void)eat
{
NSLog(@"体重为%0.1fKg的狗在吃东西",_weight);
}
//实现run方法
- (void)run
{
NSLog(@"速度为%0.1fkm/h的狗跑起来了",_speed);
}

@end

//定义主函数
int main()
{
//创建Dog类对象
Dog *d = [Dog new];
//调用set方法
[d setWeight:20];
[d setSpeed:30];
//调用eat方法
[d eat];
//调用run方法
[d run];

return 0;
}


<2>OC弱语法

OC的编译器容错能力比较强,这就说明OC是弱语法,OC是在运行程序的过程中才会去检测对象有没有实现相应的方法,编译期间是不会检测的。
#import <Foundation/Foundation.h>

// 尽管编译器容错能力比较,但是写代码必须规范
@interface Person : NSObject
- (void)test;
@end

@implementation Person
//- (void)test
//{
//    NSLog(@"哈哈哈");
//}
@end

// 一旦运行过程中出错,就会闪退

/*
-[Person test]: unrecognized selector sent to instance 0x7fd2ea4097c0
给Person对象发送了一个不能识别的消息:test
*/

int main()
{
Person *p = [Person new];
// OC是在运行过程中才会检测对象有没有实现相应的方法
[p test];
return 0;
}


2,类方法
<1>基本概念:直接可以用类名来执行的方法(类本身会在内存中占据存储空间,里面有类\对象方法列表)。
<2>类方法和对象方法的对比
#1对象方法:以减号-开头;只能让对象调用,没有对象,这个方法就根本不可能被执行;对象方法能访问实例变量(成员变量)。
#2,类方法:以加号+开头;只能用类名调用,对象不能调用;类方法中不能访问实例变量(成员变量);
#3,适用场合:当不需要访问成员变量的时候,尽量用类方法。
#4,类方法和对象方法可以同名。
//	设计一个方法输出类名
#import <Foundation/Foundation.h>

@interface Person : NSObject
{
int _age;
}
//声明类方法
+ (void)printClassName;

@end
@implementation Person
//实现类方法
+ (void)printClassName
{
NSLog(@"这个类的名字是Person");
}

@end

int main()
{
//调用类方法
[Person printClassName];

return 0;
}
3,self关键字
self是指针,代表着谁调用它,它就指向谁。
<1>当成员变量和局部变量同名时,采取就近原则,访问的是局部变量,用self可以访问成员变量,区分同名的局部变量。
<2>使用地方:所有的OC方法中(对象方法\类方法),不能使用在函数中。
<3>作用:使用“self ->成员变量名”访问当前调用者的成员变量;使用“[self 方法名];”来调用方法(对象方法\类方法)
<4>常见错误:1,用self去调用函数。2,类方法中用self调用对象方法,对象方法中调用类方法。3,self死循环。
//self练习
#import <Foundation/Foundation.h>
@interface Person : NSObject
//声明类方法
+ (void)test;
+ (void)test1;

//声明对象方法
- (void)test;
- (void)test2;
@end

@implementation Person
//实现类方法
+ (void)test
{

NSLog(@"调用了类的test方法");
//    //会引发死循环
//    [self test];
}
//实现对象方法
- (void)test
{
NSLog(@"调用了对象的test方法");
//会引发死循环
//[self test];
}
//实现类方法
+ (void)test1
{
//这里self代表的是类
[self test];
}
//实现对象方法
- (void)test2
{
//这里self代表的是对象
[self test];
}
@end

int main()
{
Person *p = [Person new];
//调用对象方法
[p test2];
//调用类方法
[Person test1];
return 0;
}
/*运行结果是:
2014-04-06 15:12:28.178 a.out[827:707] 调用了对象的test方法
2014-04-06 15:12:28.181 a.out[827:707] 调用了类的test方法
*/
4,继承
<1>继承的好处:1,抽取重复代码;2,建立了类之间的关系;3,子类可以拥有父类中的所有成员变量和方法。坏处:耦合性太强。
注意点:基本上所有的类的根类都是NSObject类。

//继承的代码体现

#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类的声明,Dog继承Animal
@interface Dog : Animal

@end
//Dog类的实现
@implementation Dog
@end

//Cat类的声明,Cat继承Animal
@interface Cat : Animal

@end
//Cat类的实现
@implementation Cat
@end

int main()
{
//创建Dog对象
Dog *d = [Dog new];
//给age赋值
[d setAge:5];
//给weight赋值
[d setWeight:30];
NSLog(@"age=%d,weight=%0.1f",[d age],[d weight]);

//创建Cat对象
Cat *c = [Cat new];
//给age赋值
[c setAge:6];
//给weight赋值
[c setWeight:10];
NSLog(@"age=%d,weight=%0.1f",[c age],[c weight]);

return 0;
}
/*运行结果是
2014-04-06 16:22:26.308 a.out[978:707] age=5,weight=30.0
2014-04-06 16:22:26.310 a.out[978:707] age=6,weight=10.0
*/
<2>继承的应用
#1,重写:子类重新实现父类中的某个方法,覆盖父类以前的做法。
#2,父类必须声明在子类的前面;子类不能拥有父类相同的成员变量;调用某个方法时,优先去当前类中找,如果找不到,去父类中找。
#import <Foundation/Foundation.h>
//声明Person类
@interface Person : NSObject
{
//定义成员变量
NSString *_name;
int _age;

}
//声明类方法
+ (void)test;
//声明name的set方法
- (void)setName:(NSString *)name;
//声明name的get方法
- (NSString *)name;

//声明age的set方法
- (void)setAge:(int)age;
//声明age的get方法
- (int)age;
//声明run方法
-(void)run;
@end

//实现Person类
@implementation Person
//实现类方法
+ (void)test
{
NSLog(@"我是Person类的类方法!!!");
}
//实现name的set方法
- (void)setName:(NSString *)name
{
_name = name;
}
//实现name的get方法
- (NSString *)name;
{
return _name;
}

//实现age的set方法
- (void)setAge:(int)age
{
_age = age;
}
//实现age的get方法
- (int)age;
{
return _age;
}
//实现run方法
- (void)run
{
NSLog(@"名字叫%@,年龄是%d的人在跑步",_name,_age);
}
@end
//声明Student子类并且继承了Person父类
//不允许子类和父类拥有相同名称的成员变量
@interface Student : Person
{
//定义成员变量
int _no;
}
+ (void)test1;
- (void)setNo:(int)no;
- (int)no;
@end
//实现Student类
@implementation Student
+ (void)test1
{
//调用test方法,先在本类中找,如果没有,然后再去父类中找,
[self test];
}

- (void)setNo:(int)no
{
_no = no;
}
- (int)no
{
return _no;
}

//重写父类Person的run方法
- (void)run
{
NSLog(@"学号为%d,名字叫%@,年龄为%d的学生在跑步",_no,_name,_age);
}
@end

int main()
{
//创建Student类对象
Student *s = [Student new];
//设置学号
[s setNo:20140010];
//设置名字
[s setName:@"张三"];
//设置年龄
[s setAge:23];
//调用子类重写后的run方法
[s run];
//调用类方法
[Student test1];
return 0;
}
/*运行结果是
2014-04-06 18:04:56.342 a.out[1104:707] 学号为20140010,名字叫张三,年龄为23的学生在跑步
2014-04-06 18:04:56.345 a.out[1104:707] 我是Person类的类方法!!!
*/

<3>继承的使用场合及组合使用

1> 当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中
2> 当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类
A
{
int _age;
int _no;
}

B : A
{
int _weight;
}
// 继承:xx 是 xxx
// 组合:xxx 拥有 xxx
2.组合
A
{
int _age;
int _no;
}

B
{
A *_a;
int _weight;
}
<4>super的作用

#1.直接调用父类中的某个方法
#2.super处在对象方法中,那么就会调用父类的对象方法; super处在类方法中,那么就会调用父类的类方法
#3.使用场合:子类重写父类的方法时想保留父类的一些行为
5,多态
<1>多态的基本概念:某一事物的多种形态;OC对象具有多态性。多态:不同对象对同一消息的不同响应.子类可以重写父类的方法。

<2>多态使用
#1.没有继承就没有多态
# 2.代码的体现:父类类型的指针指向子类对象
# 3.好处:如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象
#4.局限性: 父类类型的变量不能直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法。
//多态
#import <Foundation/Foundation.h>
@interface Animal : NSObject
- (void)eat;
@end

@implementation Animal
- (void)eat
{
NSLog(@"Animal吃东西");
}
@end

@interface Dog : Animal
- (void)run;
@end

@implementation Dog
- (void)run
{
NSLog(@"Dog跑起来了");
}
- (void)eat
{
NSLog(@"Dog吃东西");
}
@end
int main()
{
//Dog类的多态表现,Animal父类指针指向Dog子类对象
Animal *a = [Dog new];
// 调用方法时会检测对象的真实形象
[a eat];
// 多态的局限性:父类类型的变量不能用来调用子类的方法,直接调用会有警告!
/*4-多态.m:38:8: warning: 'Animal' may not respond to 'run'
[a run];
~ ^
1 warning generated.
*/
//所以将a转换为Dog类型
Dog *d = (Dog *)a;
[d run];
return 0;
}
/*运行结果为:
2014-04-06 19:41:16.678 a.out[1301:707] Dog吃东西
2014-04-06 19:41:16.679 a.out[1301:707] Dog跑起来了
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: