和Tom一起学习Objective-C 第三期


分数类


第一个Objective-C程序

这一期,我们就来正式的打出第一个具有Objective-C味道的程序。没错,如果你觉得前面几期太easy了,和C没有区别,那么以后就是和C有不同的地方的内容了。
在学习新的一期之前,还是建议回去复习一下前两期的内容。
第二期:https://www.jianshu.com/p/0bd7e58147e0
第一期:https://www.jianshu.com/p/5c27421e8828

Objective-C程序特点

Objective-C的结构主要分以下几个部分:

  • @interface部分
  • @implementation部分
  • 程序部分
1.@interface部分

@interface,顾名思义就是接口的意思,其主要作用就是定义一个新的类。
其格式为:

@interface NewClassName:ParentClassName
类的属性和方法的声明;
@end

这里就体现了面向对象编程的第一个特性「继承」,输入这么样的一个语句后,新创建的类就从原来已知的一个类继承过来,也就是说新的类具有该原来的类的属性和方法。
接下来就有两个定义:
父类:原来就存在的类,被子类所继承。
子类:新产生的类,具有父类的特性。

2.@implementation部分

@implementation,顾名思义,也就是实现的意思。
这个部分主要将@interface中声明的方法,给出定义,(也就是说把方法添加实际的代码)并指定类对象中存储的数据类型。
其一般格式如下:

@implementation NewClassName
{
成员声明;
}
方法定义;
@end
3.程序部分

程序部分就不用说了,就和前两期的代码类似,必须要有一个主函数,然后在主函数里,你可以像第二期一样,创建对象,并对对象进行操作。


下面我就准备用书中的例子来解释一下,我所讲的概念,而且这个例子中有很多的扩展部分,注意记好笔记。

在写例子之前有些注意事项需要注意一下。


注意事项

关于类的命名问题

类的命名基本上和C的变量命名类似,注意以下几点:

  • 必须以字母或下划线(_)开头,之后可以是字母、下划线或数字
  • 不能有其他非法字符
  • 不能使用系统保留字命名
  • 名称中间不能有空格
  • 如要表达空格,可以用下划线代替,这种方法有一个很非正式的说法叫做:驼峰命名法。例如,play_the_piano。
    给类命名时,要用大写;
    给对象和方法命名时,要用小写;
    如果名字中含有多个词,要用大写区分开来,比如:goToHell。
    虽然命名没什么硬性规定,但是这样的规定可以增加程序的可读性。学C的也是可以套用这些命名的规则的。

其次,就是类方法和对象方法。方法其实说白了就是函数。
看看它的格式就知道了:
类方法:
+(返回值类型) 方法名:(参数类型)参数名称
对象方法:
-(返回值类型) 方法名:(参数类型) 参数名称
和函数的定义基本就很像了,就是用「+」和「-」区分类方法和对象方法而已。


分数类(Fraction Class)

书中用了一个分数类来解释OC编程中可能遇到的问题

问题

用面向对象的方法来编写一个显示分数的程序。

分析

如果我们要创建一个分数类,然后实例化形成对象,我们应该进行怎样的操作呢?
一个分数要有分子(numerator)和分母(denominator),所以我们就先命名两个变量叫做分子和分母。
然后我们要给分子、分母赋值,所以要创建两个赋值方法。
最后,你会发现,分母、分子已经附好值了,却编译运行的时候啥也没有,GG,所以你要给它一个打印方法。

代码

#import <Foundation/Foundation.h>

@interface Fraction:NSObject

-(void) print;
-(void) setNumerator;
-(void) setDenominator;

@end

@implementation Fraction
{
    int numerator;
    int denominator;
}
-(void) setNumerator
{
    NSLog(@"请输入分子");
    scanf("%i",&numerator);
}
-(void) setDenominator
{
    NSLog(@"请输入分母");
    scanf("%i",&denominator);
}
-(void) print
{
    NSLog(@"分数为:%i/%i",numerator,denominator);
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Fraction *frac1 = [Fraction new];
        [frac1 setDenominator];
        [frac1 setNumerator];
        [frac1 print];
    }
    return 0;
}

代码解析:

@interface Fraction:NSObject
首先,这TM就很奇怪了,NSObject是什么鬼?
这个嘛,不用了解太多,只要知道NSObject就是OC里一个类似上帝般的存在就行了,你所命名的子类都是基于这个类。
这串代码就是说,我们在这个代码里进行了对类的创建。
-(void) print;
-(void) setNumerator;
-(void) setDenominator;
这是声明了分析里面三个对象方法,毕竟一个具体的分数就是一个对象嘛!
可能你会想到,分子和分母算是分数的属性,但是书里边给出的例子,并没有把分子分母写成属性,主要是因为在@interface中的属性变量是受保护的,如果应用到程序中,你会发现这些属性无法使用。(解决方法我们后期再讲,知道属性变量是受保护的就行)
@interface部分结束后,不要忘记写个@end哦。
@implementation Fraction
对分数类进行个实现

@implementation Fraction
{
   int numerator;
   int denominator;
}

这也就对应了上面的成员变量定义了,每生成一个对象,它就会有完全不同的numerator和denominator。

- (void) setNumerator
{
    NSLog(@"请输入分子");
    scanf("%i",numerator);
}

嗯,这是个对新手不太友好的教程,不过这确实是我根据原来的代码改进的,因为C和OC可以混用,所以我就用了scanf()来输入分子分母了,而不是像原来那样,要设参数,到时候还要自己在程序里输入一个在方法后面输入一个具体的参数。

-(void) print
{
    NSLog(@"分数为:%i/%i",numerator,denominator);
}

如果不创建print这个方法,直接到程序里去NSLog,你会发现没有办法访问对象里的数据,从而就没有办法显示分数了。
写完方法后,记得@end哦
最后就是程序部分了

Fraction *frac1 = [Fraction new];

语句解释:创建一个叫做frac1的对象
创建对象的格式如下:

类名 *对象名 = [类名 new];

对新手满满的恶意233
先解释一下,「Fraction *frac1」中,(*)表示,frac1是Fraction对象的引用(或指针)。变量frac1实际上不存储Fraction的数据(即分数的分子和分母),而是存储了一个引用(其实是内存地址),表明对象数据在内存中的位置。frac1并没有任何值。
这句话是书中抄过来的,比较让我纳闷的是这个引用,是C++里的引用吗?
不过如果用指针理解还是挺easy的。反正就是说这个就是字面的意思了,没什么好说的。

[类名 new];

这个用了一个叫做new的类方法,不过这个new哪来的,当然是从之前说过的万能的上帝NSObject里来的。
当然如果你想知道new经历哪些过程,你可以看如下解释:

\\[Fraction new]相当于[[Fraction alloc] init]
\\[[Fraction alloc] init]还可以写成
先[Fraction alloc],再[Fraction init]

所以说创建一个对象就有从代码层面来说就是alloc分配一块内存,init初始化。
要注意的是,当你分配过后,此时init是对对象(frac1)发送的命令,而不是对类(Fraction)发送的命令。

        [frac1 setDenominator];
        [frac1 setNumerator];
        [frac1 print];   

这就没啥技术含量,既然有对象了我们就要「搞」事情嘛
如果你记得昨天的[Tom goDie]的话,你就知道是什么意思了。就是让对象去执行里边的方法。
最后我输出的结果就是这样的



今天的内容就是初步的体验一下,用OC面向对象编程,理解下昨天所说的对象和类。
小结:
看完之后,请问自己以下几个问题:
一个OC程序的结构是怎样的?
如何创建一个类?
如何声明方法,类方法和对象方法的区别是什么?
命名变量、对象时要注意什么?
如何创建一个对象?


小剧场

垂死挣扎的C语言要出来抢个戏,不就是显示个分数吗?你这太麻烦了

#include <stdio.h>

int main(int argc, const char * argv[]) {
    int numerator;
    int denominator;
    printf("请输入分子\n");
    scanf("%d",&numerator);
    printf("请输入分母\n");
    scanf("%d",&denominator);
    printf("分数为%d/%d\n",numerator,denominator);
    return 0;
}

C:多简单,多粗暴啊。OC你学着点。
OC:来来来,你头铁你写个图形界面试试。
C:.............


这一章比较卡,再出一期我就能结束了。
下回预告:set方法和get方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容