在this post中,勇敢者希望(用C++)將類型爲Base
的對象向下轉換爲Derived
類型。假設派生類型沒有比Base
更多的屬性,那麼可以是有意義的,如果你嫉妒Derived
類提供的額外方法。哪些語言允許更改對象的身份(不是強制轉換)?
是否有編程語言允許這樣的事情?
在this post中,勇敢者希望(用C++)將類型爲Base
的對象向下轉換爲Derived
類型。假設派生類型沒有比Base
更多的屬性,那麼可以是有意義的,如果你嫉妒Derived
類提供的額外方法。哪些語言允許更改對象的身份(不是強制轉換)?
是否有編程語言允許這樣的事情?
實際上,這是在Common Lisp和CLOS(Common Lis Object System)被移植的其他Lisp方言中沒有問題的情況下完成的。您使用change-class
通用功能。
CLOS與多種調度方法一起工作,所以一個方法不綁定到一個類或對象,它只是一個函數,在一組類似函數WRT中選擇它的參數的類型(或身份)。當使用change-class
時,您可以給出參數,就好像您正在創建新實例一樣,並且已存儲在對象中的數據將保留。下面是展示它是如何工作有點會議:
CL-USER> (defclass base()
((name :initarg :name)))
#<STANDARD-CLASS BASE>
CL-USER> (defclass derived (base)
((age :initarg :age :initform 0)))
#<STANDARD-CLASS DERIVED>
CL-USER> (defvar foo (make-instance 'base :name "John Doe"))
FOO
CL-USER> (change-class foo 'derived :age 27)
#<DERIVED {100338F2D1}>
CL-USER> (with-slots (name age) foo
(list name age))
("John Doe" 27)
CL-USER> (defvar bar (make-instance 'base :name "Baby Joe"))
BAR
CL-USER> (change-class bar 'derived)
#<DERIVED {10036CF6E1}>
CL-USER> (with-slots (name age) bar
(list name age))
("Baby Joe" 0)
CL-USER>
如果這個默認的行爲是不夠的,你可以在update-instance-for-different-class
定義的方法。
所以是的,有編程語言,允許這樣的事情!
Awsome,謝謝! – CharlesB 2011-07-26 10:02:37
如果你想看看Lisp能夠做什麼,那麼有兩種可用的資源。如果你想要一些更實用的東西,那就去Peter Seibel的Practical Common Lisp(http://gigamonkeys.com/book/),如果你至少有點精通數學,並且想深刻理解本質計算機編程,嘗試SICP(http://mitpress.mit.edu/sicp/,並有視頻課程http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/) – 2011-07-26 10:52:24
不,但首先這是一種強烈的代碼味道。
一種更好的選擇是使用decorator pattern,這正是它所做的。
當你想說「我不喜歡它」時,不要回答「否」。特別是當「否」實際上是錯誤的時候... – 2011-07-26 09:53:58
如果Derived
沒有添加任何屬性,那麼它添加的方法必須在從Base
得到的狀態下運行。在那種情況下,爲什麼不把這些方法移到Base
那裏?
正是因爲@Albus對問題的評論。屬性不定義類,一個類有不同的方法具有不同的身份/功能。 – CharlesB 2011-06-06 07:41:42
這甚至是Haskell中類型類型的概念。如果它實現每個類的功能,相同的對象可以在不同的類型類中。... – 2011-07-26 10:54:23
方法是什麼定義類,而不是屬性。 – 2011-05-17 19:06:53