您好,欢迎访问本站博客!登录后台查看权限
  • 欢迎大神光临
  • 有朋自远方来 不亦悦乎

Objective-C教程之初识类

ObjC教程 老刘 2018-08-07 347 次浏览 0个评论

Objective-C class类型具有结构体一样的存储数据功能,而且具有封装继承等面向对象特性,这 是Objective-C支持面向对象最核心的语言特性。

NSObject是大部分Objective-C类的根类(继承或者间接继承自NSObject),换句话说,Objective-C 并没有规定类一定要继承自NSObject。但是继承自NSObject的类,才拥有Objective-C运行时系 统的基本接口和作为Objective-C对象的行为能力,换句话说就是NSObject实现了最最基础的功能, 一个类的继承或者间接继承自他才拥有这些基本功能。

一个简单的例子,这个例子抽象了一个人的一些基本属性的行为。

#import <Foundation/Foundation.h>

@interface MSPerson:NSObject

- (int) age;
- (void) setAge:(int)age;

@end


@implementation MSPerson {
    int age_;
}

// init是父类的一个方法 拥有初始化实列
- (instancetype)init {
// self代表类实列,类似Java、C++、C#的this
// super 访问父类的实列方法
// 先调用父类的初始化方法
    self = [super init];
    if(self) { // 父类的init可能初始化失败而返回空 因此判断一下
        [self setAge:18]; // 默认将年龄设置为18岁
    }
    return self;
}

- (int) age {
    return  age_;
}

- (void) setAge:(int)age {
    age_ = age;
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 创建一个Person对象
        MSPerson *jack = [MSPerson alloc];
        // 初始化Person对象
        [jack init];
        // 发送消息(调用对象方法)
        // [jack setAge:38];
        // 发送消息(调用对象方法)
        int jackDeAge = [jack age];
        NSLog(@"jack:age=%d", jackDeAge);
    }
    return 0;
}

类命名习惯

习惯在类的前面添加两个或者多个大写前缀,可以是公司缩写、模块名称缩写、作者昵称缩写等,目 的是避免同名冲突。比如一个项目A程序员写了个Person类,B程序员也写了个Person类型,当他们 放在一起编译的时候是编译不通过的,加上不同的前缀就可以避免冲突。在C++和C#中引入了命名空 间的语言特性来避免同名冲突,而在Java中引入了包的语言特性来避免同名冲突,他们都是语言的特 性,而Objective-C没有对应的语言特性解决该问题,添加类前缀,是一种解决这种冲突的习惯做法。

类声明和实现格式

在Objective-C中,定义一个类分两部分,接口声明和类实现,有点像C++,C++也分为类声明和类 实现两部分,但是C++允许在类声明中把功能实现了,而Objective-C是不允许的,必须有两部分。

接口声明@interface开始,@end结束。格式如下

@interface 类名:父类 {
    类成员变量
}
类方法声明
@end

声明一个自定义的类是必须继承自一个父类的,NSObject的

类实现@implementation开始,@end结束。格式如下

@implementation 类名 {
    类成员变量
}
类方法实现
@end

类成员变量

成员变量可以放在接口的{}之中,或者实现的{}之中,和C语言声明变量的语法一样,但是我们不能 在声明的地方对变量初始化,默认编译会将他们初始化为0。

实列方法方法声明语法

  • Objective-C方法以-开头;

  • 和C语言的函数语法相比返回值类型要用括号括起来;

  • 方法名遵循的是越详细越好的原则,如果有参数,那么对每个参数都有描述,并且参数的描述和冒 号也算方法名的一部分,如此麻烦的语法其实就是为了让方法理解起来更像一句完整的英文语句;

  • 每个参数类型也是要用括号括起来,之后接着形参。

下面是几种方法命名格式:

MSPerson *jack = [MSPerson alloc];

alloc不足以对类实列进行完全的初始化,因此还需要要调用init进行下一步初始化。

下面这句对jack调用实例方法init,对其进行初始化。

[jack init];

因为init会一般返回self,因此上面两步习惯写成链式调用,而且写成链式调用更加安全,因为可能init返回了新的指针,而不是alloc返回时的指针。

MSPerson *jack = [[MSPerson alloc]init];

上面两步也可以简写为

MSPerson *jack = [MSPerson new];

完成上面两边后jack已经可以使用了,比如我们可以对类进行年龄操作。

[jack setAge:38];
int jackDeAge = [jack age];

[]语法和.语法对比

我们不妨用Java/C#主流语言的点访问语法对[]进行等价替换,以加深理解。

MSPerson *jack = [[MSPerson alloc]init];

等价Java

MSPerson jack = MSPerson.alloc().init();

[jack setAge:38];
int jackDeAge = [jack age];

等价Java

jack.setAge(38);
int jackDeAge = jack.age();

已有 347 位网友参与,快来吐槽:

发表评论