=== 原文地址: 網絡: http://trac.clozure.com/ccl/wiki/CocoaBridgeTranslation
原文標題: Cocoa Bridge Translation 翻譯者: FreeBlues 2013-07-18網絡
===ide
這裏有一堆從 OBJ-C 代碼到等效的 Clozure CL 的 Cocoa 橋代碼之間的轉換,示範不一樣的語言習慣如何編碼。這些東西有些是 Clozure CL FFI 的一部分,未指定具體的橋,但它們被包含在這裏給出一個整體概覽。函數
T 和 NIL 被映射到對應的布爾值 YES 和 NO. 全部數字也是可移植的. NSStrings 須要被明確地建立:編碼
Objective-C 的代碼爲:翻譯
@"some string"
對應的 Lisp 代碼變爲:指針
#@"some string"
若是你須要在 Lisp 字符串和 NSStrings 之間作轉換, 下面的函數就是你想要的.code
(let ((a-lisp-string "foo")) (ccl::%make-nsstring a-lisp-string))
而且當你接收到 NSStrings 時,你一樣須要轉換:對象
(ccl::lisp-string-from-nsstring (#/title some-object))
Clozure CL 習慣於自動轉換字符串, 不過這很容易引發內存管理問題. 因此必定要確保你所須要的任何 NSStrings 的保持/釋放.教程
nil NULL
這兩個都是空指針. 在 Lisp 中要使用:接口
ccl:+null-ptr+
來表示它們.
在其餘一些狀況下,您可能須要使用類型(不是類)名稱, 做爲您定義的方法的返回值。
Objective-C 的代碼爲:
NSInteger BOOL
對應的 Lisp 代碼變爲:
#>NSInteger #>BOOL
Objective-C 的代碼爲:
NSTitledWindowMask NSUTF8StringEncoding
對應的 Lisp 代碼變爲:
#$NSTitledWindowMask #$NSUTF8StringEncoding
Objective-C 的代碼爲:
@selector(someSelector:withParams:)
對應的 Lisp 代碼變爲:
(@selector "someSelector:withParams:")
譯者注:就是要去掉 Objective-C 代碼裏的括號--爲了不和 Lisp 的括號發生混淆
Objective-C 的代碼爲:
@interface SomeClass : SuperClass { IBOutlet NSString *aString; }
譯者注: 這段的代碼其實是 Object-C 中對一個類的接口的定義, 保存在 .h 文件中,也就是頭文件, 使用語法形式爲:
@interface 類名:父類名 { 實例變量聲明; } - 實例方法聲明; + 類方法聲明; @end
對應的 Lisp 代碼變爲:
(defclass some-class (super-class) ((a-string :foreign-type :id)) (:metaclass ns:+ns-object))
Objective-C 的代碼爲:
@implementation SomeClass // just included so we show the class name - (id) initWithFrame:(NSRect)frame andStuff:(id)stuff { if ((self = [super initWithFrame:frame])) { // body } return self; } - (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // body }
譯者注: 這段的代碼其實是 Object-C 中對一個類的實現的定義, 具體內容爲類的方法的實現代碼, 保存在 .m 文件中,也就是存放代碼的文件中, 相似於 C 的 .c 文件, 使用的語法形式爲:
@implementation 類名 - 實例方法實現 + 類方法實現 @end
對應的 Lisp 代碼變爲:
(objc:defmethod (#/initWithFrame:andStuff: :id) ((self some-class) (frame #>NSRect) (stuff :id)) (let ((new-self (#/initWithFrame: self frame))) (when new-self ;; body ) new-self)) (objc:defmethod (#/viewDidAppear: :void) ((self some-class) (animated #>BOOL)) (call-next-method)) ;; body )
一般有 CALL-NEXT-METHOD (僅如預期在 OBJ-C 方法中工做),可是,這並不包括你在 OBJ-C 中須要的全部使用場景。如同在 init 方法中常見的,有時你須要使用跟當前方法不一樣的名字來調用一個 super-method。這就是 CALL-NEXT-METHOD 失敗的地方。在上面的例子中, 本身來處理這個問題的最簡單的方法是, 把調用 super 當作 調用 self 。
譯者注:由於 Common Lisp 的面向對象系統 CLOS 的實現機制跟 Objective-C 有很大的不一樣, Lisp 的面向對象是基於廣義函數的, 而 Objective-C 的面向對象是基於消息的, 因此這裏的 Lisp 代碼儘可能按照 Objective-C 的風格來寫了.
Objective-C 的代碼爲:
[[NSWindow alloc] initWithContentRect:NSRectMake(0, 0, 300, 300) styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:YES];
對應的 Lisp 代碼變爲:
(make-instance 'ns:ns-window :with-content-rect (ns:make-ns-rect 0 0 300 300) :style-mask #$NSTitledWindowMask :backing #$NSBackingStoreBuffered :defer t)
Objective-C 的代碼爲:
[self doSomethingToObject:anObject]; [NSDate date];
對應的 Lisp 代碼變爲:
(#/doSomethingToObject: self an-object) (#/date ns:ns-date)
譯者注: Objective-C 的方法調用語法爲:
[接收者 消息]
其中接收者是對象, 消息就是該對象要調用的方法, 因此寫成 Common Lisp 的形式就須要把先後順序調一下: 把方法函數放在前面, 調用方法函數的對象則做爲方法函數的參數傳遞給方法函數.
你可使用和調用任何其餘方法相同的方式來調用 setter ,但要想使它們的工做更像是屬性或槽,您也能夠對它們使用 SETF。
Objective-C 的代碼爲:
[self setName:aName]; self.name = aName; // provided there is a @property defined
對應的 Lisp 代碼變爲:
(#/setName: self aName)
或者是
(setf (#/name self) a-name)
而 SETF 形式不管是否有一個定義好的屬性都將工做,但必須存在一個 getter (例如 (#/name self))。這是由於 SETF 的用戶指望把保存值返回,但 Cocoa 的 setters 通常沒有返回值。