0

OC学习第2天——CLASS

 2 years ago
source link: https://www.hi-roy.com/posts/oc%E5%AD%A6%E4%B9%A0%E7%AC%AC2%E5%A4%A9class/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

OC学习第2天——CLASS

2015-02-11

在新建文件时选择os x列表下的“source”,再从右面的选项中选择“cocoa class”,填写类名以及选择存储位置后会自动生成2个文件:一个.h文件和一个.m文件,格式如下

student.h:

#import <Foundation/Foundation.h>
@interface Student : NSObject
@end</pre>
student.m:
<pre class="lang:objc decode:true">#import "Student.h"
@implementation Student
@end

其中.h文件中定义类的属性、方法,和C++一样,OC中的属性也分为3种,private、protected、public。不过方法都是public的,而且不支持重载,比如:

#import <Foundation/Foundation.h>
@interface Student : NSObject{
@protected
    NSString * name;
    unsigned int age;
@public
    NSString * sid;
}
-(NSString *) getName;
-(void) setName:(NSString *) aName;
-(unsigned int) getAge; //无参数,冒号被省略
-(void) setAge:(unsigned int) aAge;
-(void) setNA:(NSString *)aName age:(unsigned int)aAge;
-(void) setNA:(NSString *)aName :(unsigned int)aAge; //同上 2个参数  age被省略 貌似变成了2个不同的函数
//-(int) getName; //oc不支持重载,所以即便返回值类型不同也不能重名
+(void) testfuc; // + 类方法
@end

和C++不同的地方就是声明一个类的语法不再是class而变成了@interface,上面这个student类继承自NSObject,这个基类和python中的object基类类似,提供了一些基本的构造函数、析构函数等来进行初始化以及回收操作。而且,oc中方法的声明和实现是写在两个文件中的,那个.m文件中写的就是方法的具体实现代码,下面再说。

类的继承以及属性的定义还比较容易理解,不过下面那些神码加号、减号、冒号的又是神码玩意??这种语法也太奇怪了吧?这里说说我个人的理解,如果有神码错误的地方,等以后学的更深入了再来改吧。

首先,+、-这两个符号定义了这个函数究竟是实例方法(-)还是类方法(+);

接着的括号中定义了函数的返回类型;

再接下来是函数名,这里是让我感到比较别扭的地方,比如

-(void) setNA:(NSString *)aName age:(unsigned int)aAge;

调用时候使用setNA这个函数名即可,不过后面的age也算是函数名的一部分,而这部分又可以被省略掉……上面说过OC中不支持函数的重载,即便参数类型和函数的返回值不同的情况下函数名一样也会报错。不过再声明一个函数比如:-(void) setNA:(NSString *)aName otherage:(unsigned int)aAge;

或者省略掉后面的参数名却是可以的,因为此时省略了后面函数名就代表着这是2个不同的函数了。

最后是一个“:(参数类型)参数名1 可省略的函数名:(参数类型)参数名2…”不考虑那个分家了的函数名的话这里也是比较好接受的。

所以,一个函数的声明整体来说结构如下:

+ or - 函数名:(参数类型)参数名1 可省略的函数名:(参数类型)参数名2….;

接下来进入.m去实现上面声明的函数,偷懒的办法就是把声明函数的代码复制过来,再把;替换成{}即可…

#import "Student.h"
@implementation Student
-(NSString *) getName{
    return name;
}
-(void) setName:(NSString *) aName{
    name = aName;
}
-(unsigned int) getAge{
    return age;
}
-(void) setAge:(unsigned int) aAge{
    age = aAge;
}
-(void) setNA:(NSString *)aName :(unsigned int)aAge{
    name = aName;
    age = aAge;
    NSLog(@"setna 1");
}
-(void) setNA:(NSString *)aName age:(unsigned int)aAge{
    name = aName;
    age = aAge;
    NSLog(@"setna 2");
}
+(void) testfuc{
    NSLog(@"is a class fuc");
}
@end

最后就是在主文件中引入我们写的类以及创建对象了,代码如下

#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
    Student * astduent = [[Student alloc] init]; //oc中内存都在堆上分配,所以要指针类型
    //Student *bstduent = [Stduent new];    //另一种方式创建
    astduent->sid = @"nsstring";// public属性直接访问
    [Student testfuc]; //类方法调用
    [astduent setName:@"abc"]; //实例方法掉用
    [astduent setNA:@"abc1" : 15];
    [astduent setNA:@"abc2" age:17];
    NSLog(@"student name is %@",[astduent getName]); //getName其实是一个返回NSString类型的函数
    NSLog(@"student age is %d",[astduent getAge]);
    }
    return 0;
}

至于@ [ ]的意思上文中已经说过了,至于alloc、init方法就是在基类中定义的,至于第二种方式引用一下别人的解释吧:

new方法是NSObject对象的一个静态方法,根据apple的文档,该方法实际上就是alloc和init方法的组合,实际上二者是一样的,但 apple还是推荐我们使用第一种方法,为什么呢?因为使用第一种方法,你可以使用自己定义的init方法来做一些初始化,当然,如果子类没有提供 init方法,自然调用的就是父类的init方法了。所以说,从安全性的角度来收,作为开发者我们在对象使用之前是一定要对对象进行初始化的,因此在定义类的时候一定要提供初始化方法。但是否一定要使用init作为方法名呢?答案是不一定。使用init作为方法名只是你重写了NSObject的init方法而已,如果你自己重新定义一个初始化方法,也是完全可以的,只要你在使用的时候记得调用新定义的初始化方法就可以了。

引用来源:http://www.oschina.net/question/54100_32468

最后看输出,也说明了上面的一点:

2015-02-11 21:52:43.506 helloword[1069:146145] is a class fuc
2015-02-11 21:52:43.507 helloword[1069:146145] setna 1
2015-02-11 21:52:43.507 helloword[1069:146145] setna 2
2015-02-11 21:52:43.507 helloword[1069:146145] student name is abcd
2015-02-11 21:52:43.507 helloword[1069:146145] student age is 17

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK