阅读更多

2顶
0踩

移动开发
本文的作者Anton Zherdev是一名具有多年开发经验的独立游戏开发者,他从一个专业开发者的视角深入剖析Objective-C,将其与C、Java等其他语言相比,解读Objective-C的优与缺,以最为精炼的话语总结出他所认为的Objective-C的13件最为糟糕的事,直指Objective-C的不足之处,与列位开发者分享。以下为文章全文:

1. 笨重的语法

在Objective-C中,必须要编写大量的代码来声明一个类或属性。对比下面的Objective-C和Scala的代码段,效果不言而喻。

@interface Foo : NSObject  
@property (readonly) int bar;  
- (instancetype)initWithBar:(int)bar;  
+ (instancetype)fooWithBar:(int)bar;  
@end  
@implementation Foo  
- (instancetype)initWithBar:(int)bar {  
   self = [super init];  
   if (self) {  
       _bar = bar;  
   }  
   return self;  
}  
+ (instancetype)fooWithBar:(int)bar {  
   return [[self alloc] initWithBar:bar];  
}  
@end  

class Foo {  
   private int bar;  
   public Foo(int bar) {  
        this.bar = bar;  
   }  
   public int getBar() {  
        return bar;  
   }  
}  

class Foo(bar : Int)  


2. 方括号

前缀括号是一件非常虐心的事情,尽管Objective-C有IDE自动解决这一问题,却也大大降低了代码的可读性。

3. 内存管理

与具有垃圾回收器的编程语言相比,Objective-C的内存更容易泄漏。虽然垃圾回收器可能会导致程序不定时回收,但也可通过设置来避免。在Objective-C中,尽管已经有ARC来解决这一问题,并且,开发者可以很好地利用它来解决一些弱引用的问题,却还存在着无法解析引用周期的状况。

举个例子,如果你在block中使用self,并将其发送给另一个存储该block的类,便会导致内存泄漏,而且还很难发现。并且,如果想要在类字段中保存block,就必须要将其copy过来,否则,当block被调用时,程序也就崩溃了。

4. 动态且不安全的类型系统

Objective-C有一个非常奇怪的类型系统。任何消息,只要在视图中可声明,就可以将其发送给id类对象,但却无法回避id。

@interface Foo : NSObject  
- (void)foo;  
@end  
@implementation Foo  
- (void)foo{}  
@end  
   
@interface Bar : NSObject  
- (void)bar;  
@end  
@implementation Bar  
- (void)bar {  
  [(id)self foo]; //OK  
  [(id)self bar]; //OK, but runtime error  
  [(id)self qux]; //Compiler error  
  Foo* foo = self; //OK  
}  
@end  


5. 不支持泛型

在Objective-C中,要想查看容器类所属是不可能的,而且,编译器也不能进行检查。这方面,Java显然要好得多。

NSArray* array = [foo array];  
id item = [array objectAtIndex:0]; //item is anything  

List<A> array = foo.getArray();  
A item = array.get(0);  


6. 核心库集匮乏

在Objective-C的核心库中,缺少诸如分类设置、字典(地图)、链表、队列等实用集。没有它们,在进行红黑树分类和字典等开发管理时会花费大量的时间。

还有一个问题就是缺乏几项非常不错的功能,尤其是函数式编程能力有所缺失,尽管如此,但在Objective中,也有非常不错的一项功能,就是开发者可以使用分类简单地扩展核心集。

7. 缺少枚举

尽管Objective-C包含有C的枚举,但却仅仅只是一组变量,开发者必须要编写代码来实现一些类似于Java的枚举,比如链接属性等。

enum Foo {  
    Foo1(1),  
    Foo2(2),  
    Foo2(3);  
    final int bar;  
    Foo(int bar) {  
        this.bar = bar;  
    }  
}  


8. 可怕的block语法

block是Objective-C一项非常强大的功能,但我却不知如何声明带有block类型的变量或函数参数。看下面这段代码便可知晓。

//Declare variable foo  
void (^foo)(id obj, NSUInteger idx, BOOL *stop);  


9. 操作符重载缺失

如果说无需操作符重载的话,难免有些欠妥,因为定义向量数学运算符是件很正常的事情,它使代码更具有可读性。

 [[[a add:b] sub:[c mul:f]] div:f];  
(a + b - c*f)/f;  


10. 匿名类不足

定义一个协议或接口并不像想象中那么简单,要想轻而易举地实现,就必须要先实现一个完整的类。

@protocol I  
- (void)f;  
@end  
   
@interface Foo : NSObject  
- (void)foo;  
- (void)qux;  
@end  
@implementation Foo  
- (void)foo {  
   id<I> i = [[Baz alloc] initWithFoo:self];  
}  
@end  
   
@interface Baz : NSObject<I>  
- (instancetype)initWithFoo:(Foo*)foo;  
@end  
@implementation B {  
    Foo* _foo;  
}  
   
- (instancetype)initWithFoo:(Foo*)foo {  
   self = [super init];  
   if(self) {  
   _foo = foo;  
}  
   return self;  
}  
   
- (void)f {  
   [_foo bar];  
}  
@end  

interface I {  
   void f();  
}  
   
class Foo {  
   void foo() {  
       I i = new I() {  
         void f() {  
             bar();  
         }  
     };  
  }  
  void bar() {  
  }  
}  


11. 糟糕的构造函数

使用构造函数创建新对象很常见,但在Objective-C中,要想创建对象,还需调用两个函数。当然,开发者可以编写方法直接避免该问题的发生。

@interface Foo : NSObject  
- (instancetype)initWithBar:(int)bar;  
+ (instancetype)newWithBar:(int)bar;  
@end  
@implementation Foo {  
     int* _bar;  
}  
- (instancetype)initWithBar:(int)bar {  
   self = [super init];  
   if(self) {  
   _bar = bar;  
  }  
  return self;  
}  
+ (instancetype)newWithBar:(int)bar {  
   return [[self alloc] initWithI:bar];  
}  
@end  


12. 不透明的数值包装器

在Objective-C中,要想在集合或其他容器中使用数值是件很费劲的事情,除了原有代码之外,还需添加一个NSNumber类

int a = 1;  
int b = 2;  
int c = a + b;  
NSNumber* aWrap = @(a);  
NSNumber* bWrap = @(b);  
NSNumber* cWrap = @([aWrap intValue] + [bWrap intValue]);  


13. 缺乏包管理系统

在Objective-C中,开发者必须要使用到前缀,以避免类名重合。此外,还要在头文件中对所需类进行声明,以防头文件冲突,编译失败。

文章来源:Anton Zherdev个人博客 (编译/唐小引)
来自: CSDN
2
0
评论 共 4 条 请登录后发表评论
4 楼 houyujiangjun 2014-12-19 10:28
不支持泛型 还怎么好好地玩耍?
3 楼 hd700 2013-12-23 09:08
在移动终端objective-c的内存管理可比java的垃圾回收高效多了,在ARC下出现泄漏主要是对语法不熟悉。
2 楼 witcheryne 2013-12-20 21:29
第五条确实会让人头疼.
1 楼 abeibenren 2013-12-20 12:03
1.不懂
2.同意
3.开发者功底问题吧……
4.翻译的不对……Objective-C has a very strange type system. You can send any message to an object of type id if this message is declared anywhere in the view area.不同意,对于mop来讲,这不是什么问题,而且更自然

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

Global site tag (gtag.js) - Google Analytics