代码之家  ›  专栏  ›  技术社区  ›  Todd Ditchendorf

将Java代码移植到ObjC时,如何最好地表示已检查的异常?

  •  8
  • Todd Ditchendorf  · 技术社区  · 15 年前

    我正在将Java代码库移植到Cocoa/Objective-C,以便在桌面Mac OS X上使用 太多了 太多了 包含选中异常的方法的列表,如:

    double asNumber() throws FooException {
        ...
    }
    

    - (CGFloat)asNumber { 
        ... // possibly [FooException raise:format:];
    }
    

    - (CGFloat)asNumberError:(NSError **)outError {
        ...
    }
    

    我觉得对于Objective-C,输出错误通常是更好的解决方案,但正如您所看到的。。。很多像上面这样的方法看起来会很尴尬。而且,还有 太多了 其中之一。

    当然要记住,因为这些都是 选中的 Java中的异常,我需要添加 @try 块或 if (*outError) {...} 检查调用这些方法的位置( 太多了 (地点)。

    我记得我进来的时候听到过 @试一试 块在Objective-C中曾经很昂贵,但在64位或SL或其他一些新的环境中却很便宜(不完全记得)。我一点也不担心向后兼容性,所以我很担心 肯定

    6 回复  |  直到 15 年前
        1
  •  16
  •   Quinn Taylor    15 年前

    你应该 绝对避免例外 用于从字符串解析数字之类的事情。在Objective-C中,异常表示程序员错误,而不是用户输入错误,甚至是不可用的文件。(部分原因是异常处理总是比更“常规”的错误处理成本更高、更复杂 entering @try blocks is "zero cost" in 64-bit 当然,您可以随心所欲地使用异常,但这不是Cocoa方法,您会发现自己与其他Objective-C代码不一致。使用您的代码的人会非常恼火,因为您在只会导致错误的情况下抛出异常。

    从…起 Apple's own docs

    “在许多环境中,异常的使用相当普遍。例如,您可能会抛出一个异常来表示例程无法正常执行–例如,当文件丢失或数据无法正确解析时。在Objective-C中,异常是资源密集型的。您不应该将异常用于一般流控制,或者仅仅是表示错误。相反,您应该使用方法或函数的返回值来指示已发生错误,并在错误对象中提供有关问题的信息。”

    看看内置的Cocoa类如何处理这样的错误。例如 NSString 有这样的方法 -floatValue NSScanner 是吗,比如在 -scanFloat: YES NO 基于解析是否成功。

    除了Obejctive-C约定和最佳实践之外,NSError比NSException更健壮、更灵活,并且允许调用方在需要时有效地忽略问题。我建议通读这本书 Error Handling Programming Guide For Cocoa . 注: 如果你接受 NSError** NULL 如果他们不想收到任何错误信息。我所知道的每个Cocoa类都会针对错误执行此操作,包括NSString。

    尽管移植的代码可能最终看起来与Java代码完全不同,但要认识到Objective-C代码将使用它,而不是Java等价物的相同客户端。绝对符合语言的习惯用法。端口将不会是Java代码的镜像,但结果会更正确(对于Objective-C)。

        2
  •  7
  •   Chris Hanson    15 年前

    在Cocoa中,异常实际上只用于“编程错误”;其原理是让应用程序捕捉它们,让用户选择保存正在执行的操作,然后退出。首先,并非所有框架或代码路径都是100%异常安全的,因此这可能是唯一安全的操作过程。对于可以预期并从中恢复的错误,应该使用NSError,通常是通过out参数。

        3
  •  3
  •   Dave DeLong    15 年前

    您正确地认为“对于ObjC,输出错误通常是更好的解决方案”。在Cocoa中很少会发现抛出异常的API(除非您没有满足API的先决条件,但在这种情况下,默认情况下行为是未定义的)。

    如果您希望此代码超出您的范围,并被其他Cocoa开发人员采用,我建议使用out错误。我从事的代码是由不熟悉Cocoa的人构建的,他们大量使用异常,解决异常是一件非常痛苦的事情。

        4
  •  2
  •   Ben Gotow Dmitry Nogin    15 年前

    我非常喜欢Objective-C使用的输出错误方法。您必须处理异常,但如果愿意,您可以选择忽略错误。它完全符合Objective-C的态度,即“程序员知道他们在做什么”。它还使Objective-C成为一种外观非常干净的语言,因为您的代码没有被try-catch块弄乱。

    也就是说,您可能需要考虑:是否存在忽略异常的场景?你抛出的异常是真的吗 批评的 ? 您是否发现自己正在编写简单的catch块来清理变量并继续?我倾向于排除错误,因为我喜欢语法,Objective-C只为最关键的错误保留例外。

        5
  •  2
  •   Gabriel    15 年前

    看起来这些已检查的异常更清楚地映射出错误。例外情况仍然可以使用,但应为特殊情况保留。

        6
  •  -1
  •   Quinn Taylor    15 年前

    异常可能是最好的方法,因为64位Obj-CABI(运行时)使用零成本异常,所以您可以在不需要实际成本的情况下获得更干净的代码。当然,在32位中,旧的SETJMP/LangJMP异常仍然在使用,它们不与C++交互,所以如果这是一个目标,那么你就有问题了。