星期四, 2月 04, 2010

Programming 的 convergence

我以 C++ 為基地,遊走於 C#、Java、Objective-C、Ruby……都是在OOP的圈子轉呀轉。

可能是 Apple Mac OS X、iPhone OS 帶起了更多人去做 Cocoa 編程,愈來愈看到 Cocoa Objective-C 的哲學滲入 C++, Java, C# 的世界。

Objective-C 是一種 dynamic binding, typeless 的語言,而 C++, C#, Java 則是 typed 的 programming languages. C++ 的 Boost library 提供了 boost::bind 來盡量模擬 Objective-C 的 dynamic binding。我覺得 Cocoa frameworks 及其前身 NeXTSTEP, OpenSTEP 之所以成功(well, technically, not commercially...)就是因為他是活用 objective-C 語言的 dynamic binding。所以十多年前 Microsoft 在創製他的 MFC 時便引進了 DECLARE_DYNAMIC, DECLARE_DYNCREATE 之類的 macro 來扮演某程度的 dynamic binding.

當然,C++ 始終是 C++,他是 compile time binding 的,不是 runtime binding。所謂的 DYNCREATE 即 dynamic creation,就是今天我們熟識的 factory design pattern. 可是當年連 design pattern 這個 concept 還沒有呢。

在 Java 及 C# 的世界,可以用 reflection 來達成 runtime binding. 將此道運用得出神入化的應該是 Apple WebObjects 了吧。其實, WebObjects 1至4版是 Objective-C 的,5版是把他移殖到 Java,所以把大量的 Objective-C 的風格、編程哲學都帶到 Java 世界。

更有趣的要算是 POCO library。他開宗明義說要成為 C++ 中的 Cocoa frameworks。

可能是《Effective C++》書中所討論的 reference counting smart pointer 跟 std::auto_ptr 的「先入為主」,我一直都搞不清 Poco::AutoPtr 的用法。最近終於搞定了。

《Effective C++》中的 reference counting smart pointer 是自動做 reference counting,而 Poco::RefCountedObject 是手動的。

POCO 的 Poco::AutoPtr 和 Poco::RefCountedObject 是分工的,而且跟 std::auto_ptr 一點關係也沒有,雖然他們都是叫「auto pointer」。 POCO 的 auto pointer 意思是會 auto release 的 pointer。

跟 Cocoa 來作比較便很清楚:

C++:
class Xyz:public Poco::RefCountedObject
{...}

Xyz 是有 reference counting 的功能。Poco::RefCountedObject 只提供 reference counting 的功能。

要 create 一個 Xyz class 的 object instance,用 new:

Xyz *x=new Xyz;

要把 x 殺掉,當然可以用 delete,但也可以用 Poco::RefCountedObject::release()

x->release();

Look! 是不是跟 NSObject 的 retain, release 很像呢?

C++ POCO VS Cocoa:

Xyz *x=new Xyz; ~~~ x=[[Xyz alloc] init]; // reference count = 1
x->duplicate(); ~~~ [x retain]; // reference count = 2
x->duplicate(); ~~~ [x retain]; // reference count = 3

x->release(); ~~~ [x release]; // reference count = 2
x->release(); ~~~ [x release]; // reference count = 1
x->release(); ~~~ [x release]; // reference count = 0 => destroy the object.


而 Poco::AutoPtr 的用法就是要扮 Cocoa 中的 autorelease.

C++ POCO VS Cocoa:

Poco::AutoPtr x=new Xyz; ~~~ x=[[[Xyz alloc] init] autorelease];

沒有留言: