我發現在 Common Lisp 中進行面向物件編程很痛苦。主要問題是方法的命名。請參見下面的代碼。
(defclass foo () ())
(defmethod action ((object foo))
(write-line "hello"))
(defclass bar () ())
(defmethod action ((object bar) boo)
t)
(print
(action (make-instance 'foo)))
(print
(action (make-instance 'bar) 1))
這兩種action方法不是相同泛型函式的不同實作。他們有相同的名字是偶然的。但是 Common Lisp 要求所有具有相同名稱的方法具有相同數量的引數。
為了避免名稱沖突,我通常在方法名稱前加上類名,例如foo-action和bar-action。但這會導致代碼在實際程式中非常冗長,例如(lengthy-class-name-do-something some-variable).
其他面向物件的編程語言,如 C 和 Java,則沒有這樣的問題。你可以這樣寫,some_variable.do_something()其中沒有名稱沖突。
所以我想知道上述問題是否存在更好的解決方案?
謝謝你。
uj5u.com熱心網友回復:
關鍵的區別確實是方法是泛型函式上的方法。它們不是類的方法。
這聽起來像是為了文字而說話。但它應該會極大地影響您的命名選擇。“Action”對于一個通用函式來說是一個相當平淡的名字。當foo行動時,它實際上做了什么?當bar行動時,它實際上做了什么?
如果action真的是最好的名字,是否有 afoo:action和 abar:action有意義(即,action在foo包中,一個在bar包中)?他們是不同的GF。當然,缺點是不再像呼叫action它們那樣容易。
這暗示了“您不需要方法,只需使用函式即可”,因為您不需要方法來處理 CL 中的類。
uj5u.com熱心網友回復:
這兩個方法是同一個泛型函式的方法,因此它們絕對必須具有兼容的 lambda 串列。否則,無法保證有效方法組合的決議(發生在運行時,因為這是運行時多型性)具有明確的結果。
您省略了defgeneric表單,這應該會給您來自編譯器的警告。
正如您所描述的,這僅適用于 Java,因為您通常將每個類放入其自己的名稱空間中。但是在這里,您在一個命名空間中作業,并期望相同的名稱(符號)具有兩種完全不同的含義。這行不通。
在 Java 語言中,每個泛型函式都是它自己的介面。
另外,為了說明優勢:您不需要將此介面的實作附加到一個類,但您甚至可以有多個類來調度(在運行時)。這使得例如臭名昭??著的復雜訪問者模式過時了。
想象一下 Java 中的頂級語法(即作為classor的替代方案interface:
method IAction (Foo foo, Bar bar) {
action (Foo foo, Bar bar) {
return something(...);
}
}
當在運行時呼叫IAction#action獲取類的物件Foo和Bar. 當然,這在 Java 中不存在(而且似乎很難添加)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/407137.html
標籤:
下一篇:使用泛型在java中實作工廠模式
