zoukankan      html  css  js  c++  java
  • 【转】Effective-Objective-C-读书笔记-Item-4-如何正确定义常量 -- 不错

    原文网址:http://tutuge.me/2015/03/11/Effective-Objective-C-%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-Item-4-%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E5%AE%9A%E4%B9%89%E5%B8%B8%E9%87%8F/

    前言

    写博客果然比光看书要花时间=。=,书都快看完了,才写到第4节。但是总结一遍,的确印象深刻啊~~

    这次的主题是“常量”,非常常用,又非常重要的东西~良好的代码规范、设计,少不了各种常量

    Item 4 - Prefer Typed Constants to Preprocessor #define

    本节着重对比了常量的定义形式,类型常量和#define的区别、各自的特点。最后得出,我们应该用带有类型的常量,而不是#define。

    一个简单的示例

    应用中,少不了各种动画,也就少不了设定动画的时间长度,一般来说,我们会设定短、中、长几种时间常量,用于不同的场合,了解C语言的童鞋估计对“#define”宏定义不陌生,于是,可能就会如下这么定义:

    1
    2
    3
    #define ANIMATION_DURATION_SHORT 0.3
    #define ANIMATION_DURATION_MIDDLE 0.6
    #define ANIMATION_DURATION_LONG 1.0

    于是,所有用到动画时长的地方,直接用这几个宏定义就行了。

    乍一看,似乎没什么问题。

    类型+不可变

    先来看看宏定义干了什么。
    总的来说,#define就是“替换”,在编译时,将一切宏定义替换成定义后面的内容。(参考百度百科

    关键在于:

    • 宏定义不会检查替换的“类型”,只要遇到,就做替换。
    • 宏定义不保证“不可变”,因为可以重复定义,不能保证值不变。(这个我觉得是最容易让人忽略的地方)

    所以,用宏定义定义常量,很“危险”。

    正确的做法

    恰当的常量,应该具备合适的常量名字、正确的类型,还有const、extern等关键字的修饰,当然,还要根据常量适用的“范围”,做出恰当的处理。一下举例说明。

    只在函数中用的常量

    只在函数中用的常量:

    1
    2
    3
    4
    5
    - (void)runAnimation {
    //动画时间长度常量
    static const NSTimeInterval kAnimationDurationLong = 1.0f;
    //...
    }

    static、const定义了它是静态不可变的;NSTimeInterval则“精确”指定了常量的类型。

    只在一个“.m”文件中使用的常量

    在类的实现文件“xxx.m”文件中定义常量,也是很常见的。
    你可能会觉得,既然是一个类使用的,那就放在类的头文件里面定义不就好了。
    但是这么想是错的=。=
    因为所有要用到这个类的文件,都会无形当中包含了这些常量声明,将不必要的数据暴露在外面,这样是违反设计原则的,并且,如果常量名字取得不恰当,还有可能造成冲突。

    所以,应该如下:

    1
    2
    3
    4
    5
    6
    7
    8
    //XXX.m

    //必须要static
    static const NSTimeInterval kAnimationDurationLong = 1.0f;

    @implementation XXX
    //...
    @end

    需要注意的点:

    • 一定要放在.m文件中。
    • 必须是static,表示此常量作用域只在此.m文件中。如果不加static的话,常量就会在全局作用域中声明,可能会导致跟其他的常量冲突。
    • const,当然。
    • NSTimeInterval,确定的类型。
    • kAnimationDurationLong,“k”开头的命名,也算是Apple的规范了吧,内部常量统一以“k”开头。

    全局常量

    一般来说,最常见的全局常量就是发广播Notification时用的Notification的名字,往往都是一些字符串,下面就以这个为例子:

    假设我们的类叫“TTGClass”,我们的类会向外发送Notification,所以需要定义一个Notification的名字常量供外界注册,如下:

    1
    2
    3
    4
    5
    //TTGClass.h
    extern NSString * const TTGClassWorkBeginNotification;

    //TTGClass.m
    NSString * const TTGClassWorkBeginNotification = @"TTGClassWorkBeginNotification";

    关键:

    • 头文件中只是做声明,不做定义。所以用extern表示常量在别处定义的,尽量隐藏细节。
    • 类名做常量名字的开头,这个非常关键,因为Objective-C里面没有像Java那样的“包”机制,所以必须靠命名来划分不同的类,常量当然也要遵循这个规则。
    • NSString,确定的类型;const,表明常量;Notification后缀,表明用途。这些都是需要注意的。

    总结

    良好的代码,总是少不了定义各种常量,以避免“魔鬼数字、魔鬼字符串”。所以我们应该尽量避免少用#define定义常量,而是用带有类型的、const的常量,并且尽可能的缩小常量的作用域。

    暴露的细节越少,出错的机会也就越小(忘了从哪里看到的=。=)

  • 相关阅读:
    Spring 中出现Element : property Bean definitions can have zero or more properties. Property elements correspond to JavaBean setter methods exposed by the bean classes. Spring supports primitives, refer
    java定时器schedule和scheduleAtFixedRate区别
    hql语句中的select字句和from 字句
    使用maven搭建hibernate的pom文件配置
    Failure to transfer org.apache.maven:maven-archiver:pom:2.5 from http://repo.maven.apache.org/ maven2 was cached in the local repository, resolution will not be reattempted until the update interv
    对于文件File类型中的目录分隔符
    hibernate的事务管理和session对象的详解
    解决mac 中的myeclipse控制台中文乱码问题
    ibatis selectKey用法问题
    Java中getResourceAsStream的用法
  • 原文地址:https://www.cnblogs.com/wi100sh/p/5566757.html
Copyright © 2011-2022 走看看