【IOS 开发学习总结-OC-8.1】★★ objective-c面向对象之——类和对象(上)

来源:互联网 发布:尤克里里 调音软件 编辑:程序博客网 时间:2024/05/22 08:53

OC 是面向对象的语言。类,可以被认为是一种自定义的数据类型,使用它可以定义变量。所有用类定义的变量都是指针类型的变量,他们将会指向该类的类型。——就像现实世界中描述某一类对象的共同特征,对象是类的具体存在。
objective-c 也支持面向对象的三大特征:封装,继承和多态。

类和对象

所有的类都是指针类型的变量。

定义类

面向对象的程序设计过程有2个重要概念:类(class) 和对象(object,也称实例)。

类 对象 某一类对象的抽象 类具体的实例

objective-c 定义类有2个方面内容:
接口部分:定义该类包含的成员变量和方法。一般来说,我们将定义类的接口声明部分放在头文件中。定义类接口部分的源代码应该命名为.h 文件。
实现部分:为该类的方法提供实现。

接口部分

接口部分的语法如图:
这里写图片描述
对面向对象编程来说,成员变量和方法都是非常重要的概念。
- 成员变量:用于描述该类的对象的状态数据。如,我们定义一个苹果,可能需要关心它的重量,颜色,高度等状态数据,这些状态数据就应该定义为成员变量。
定义成员变量的语法格式:类型 成员变量名; 其中,类型:可以是 OC 语言允许的任何数据类型;成员变量:应该由一个或多个有意义的单词连缀而成,第一个单词首字母小写,后面每个字母首字母大写,其他字母全小写,单词间无任何间隔符。从 Xcode4开始,OC建议成员变量以下划线(_)开头。
- 方法:用于描述该类的行为。比如,程序关心人走路,吃饭,工作等行为,那么程序就应该为这个人声明走路,吃饭,工作等方法。
方法声明的语法说明:
1. 方法类型标识:+代表类方法,需用类名进行调用;-代表是实例方法,必须用对象才能调用。
2. 方法返回值类型:可以是 OC 允许的任何数据类型。如果声明了方法的返回值类型,则方法体内必须有一个有效的 return 语句,该语句返回一个变量或是表达式,类型必须与此处声明的类型匹配。如果一个方法没有返回值,必须使用 void 来声明没有返回值。
3. 方法签名关键字:由方法名,形参标签和冒号组成。方法名命名规则与成员变量命名规则基本相同,但不需要以下划线开头,通常建议方法名以英文动词开头。除第一个形参外,oc 建议为后面每个形参都指定一个”形参标签”——说明该形参的作用。一旦在定义方法时指定了形参列表,则调用该方法时必须传入对应的值——谁调用方法,谁负责给形参赋值。
这里写图片描述
注意:
objective-c 的方法声明中,所有的类型(包括 void) 都应该用圆括号括起来,这是 objective-c 与 c 函数的区别之处。另外,objective-c 中方法签名中的冒号有特殊意义。比如:foo 方法和 foo: 方法是不同的,前者不带冒号,表明是一个不带形参声明的方法;后者带一个冒号,表明它是带一个形参声明的方法。

实现部分

定义实现部分的语法格式如下:
这里写图片描述
类实现部分的说明:
1. 类实现部分的类名必须与类接口部分的类名相同。用于表示这是同一个类的接口部分。
2. 类实现部分也可以在类名后使用”:父类”来表示继承了某个父类,但一般没有必要,通常都不会这么做。
3. 类实现部分也可以声明成员变量,但这些成员变量只能在当前类内访问。因此,在类实现部分声明的变量相当于定义隐藏的成员变量。
4. 类实现部分必须为类声明部分的每个方法提供方法定义。实现部分除了实现类接口部分定义的方法外,也可以提供附加的方法定义——没有在接口部分定义,在实现部分定义的方法,只能在类实现部分使用。
示例代码:
FKPerson 类的接口部分,头文件FKPerson.h:

#import <Foundation/Foundation.h>@interface FKPerson : NSObject{    // 下面定义了两个成员变量    NSString* _name;    int _age;}// 下面定义了一个setName: andAge:方法- (void) setName:(NSString*) name andAge: (int) age;// 下面定义了一个say:方法, 并不提供实现- (void) say: (NSString *) content;// 下面定义了一个不带形参的info方法- (NSString*) info;// 定义一个类方法+ (void) foo;@end

FKPerson 类的实现部分,FKPerson.m.

#import "FKPerson.h"@implementation FKPerson{    // 定义一个只能在实现部分使用的成员变量(被隐藏的成员变量)    int _testAttr;}// 下面定义了一个setName: andAge:方法- (void) setName:(NSString*) n andAge: (int) a // ①说明在代码后{    _name = n;    _age = a;}// 下面定义了一个say方法- (void) say: (NSString *) content{    NSLog(@"%@" , content);}// 下面定义了一个不带形参的info方法- (NSString*) info{    [self test];    return [NSString stringWithFormat:        @"我是一个人,名字为:%@,年龄为%d。" , _name ,_age];}// 定义一个只能在实现部分使用的方法(被隐藏的方法)- (void) test{    NSLog(@"--只在实现部分定义的test方法--");}// 定义一个类方法+ (void) foo{    NSLog(@"FKPerson类的类方法,通过类名调用");}@end

标注①中方法与类接口部分定义的方法签名略有不同——方法形参名不同,这是允许的。对于 objective-c 来说,方法的形参名仅仅相当于一个占位符,因此方法声明中的形参名和方法实现中的形参名可以不同。
在这里,如果让 setName: andAge: 方法的形参名依然保持_name和_age反而更麻烦,因为这个形参名和接口部分定义的成员变量重名,这样局部变量将会隐藏成员变量。编译器会报警。

对象

类的3种使用方式

定义类后,使用类的3种情况分别是:
1. 定义变量。语法格式为:类名* 变量名;
2. 创建对象。语法格式为:[[类名 alloc] 初始化方法];
3. 调用类方法
创建对象用到了 alloc 关键字,alloc 负责为该类分配内存空间,创建对象。同时还需要用初始化方法对该实例进行初始化。所有的类都有一个默认的初始化方法:init, 因为所有的对象都继承了 NSObject 类。
另外,还有一个不建议多用的创建对象的方法。据说,是为了照顾 JAVA 程序员的习惯。OC 也支持用 new 来创建对象。语法格式:[类名 new]; 这种写法基本等同于:[[类名 alloc] init];

▶这里有个语句理解和使用的技巧◀
方法的主谓宾:无论是调用类方法,还是调用实例方法,都可以用”强东喝奶茶”这样的主谓宾格式进行类比。换成 objective-c 的写法,就是:[强东 喝:奶茶]; ,这里主语就是方法调用者,谓语就是面向对象中的方法,宾语是面向对象中的参数。这样我们就理解了,objective-c 调用方法的语法格式:[调用者 方法名:参数 形参标签:参数值 ... ];

objective-c规定:实例(对象)方法(-声明的方法)必须用实例(对象);类方法(+声明的方法)必须由类调用。
示例代码:
FKPerson.h头文件中代码。

#import <Foundation/Foundation.h>@interface FKPerson : NSObject{    // 下面定义了两个成员变量    NSString* _name;    int _age;}// 下面定义了一个setName: andAge:方法- (void) setName:(NSString*) name andAge: (int) age;// 下面定义了一个say:方法, 并不提供实现- (void) say: (NSString *) content;// 下面定义了一个不带形参的info方法- (NSString*) info;// 定义一个类方法+ (void) foo;@end

FKPerson.m 文件:

#import "FKPerson.h"@implementation FKPerson{    // 定义一个只能在实现部分使用的成员变量(被隐藏的成员变量)    int _testAttr;}// 下面定义了一个setName: andAge:方法- (void) setName:(NSString*) n andAge: (int) a // ①{    _name = n;    _age = a;}// 下面定义了一个say方法- (void) say: (NSString *) content{    NSLog(@"%@" , content);}// 下面定义了一个不带形参的info方法- (NSString*) info{    [self test];    return [NSString stringWithFormat:        @"我是一个人,名字为:%@,年龄为%d。" , _name ,_age];}// 定义一个只能在实现部分使用的方法(被隐藏的方法)- (void) test{    NSLog(@"--只在实现部分定义的test方法--");}// 定义一个类方法+ (void) foo{    NSLog(@"FKPerson类的类方法,通过类名调用");}@end

FKPersonTest.m实现文件。

#import <Foundation/Foundation.h>#import "FKPerson.h"int main(int argc , char * argv[]) {    @autoreleasepool{        // 定义FKPerson*类型的变量        FKPerson* person;        // 创建FKPerson对象,赋给person变量        person = [[FKPerson alloc] init];        // 调用有参数的方法,必须传入参数        [person say:@"Hello, I love iOS"];        [person setName: @"孙悟空" andAge: 500];        // 调用无参数的方法,不需要传入参数        // 方法有返回值,可以定义一个类型匹配的变量,来接收返回值        NSString* info = [person info];        NSLog(@"person的info信息为:%@" , info);        // 下面调用test方法将会引起错误。        // 因为test方法是在实现部分定义的,应该被隐藏//      [person test];        // 通过类名来调用类方法        [FKPerson foo];        // 将person变量的值赋值给p2变量        FKPerson* p2 = person;    }}
0 0
原创粉丝点击