這是不可能的,所以如果你不希望允許實現使用可變變量它只是爲了更好地隱藏這一切,並揭露功能的getter/setter:
class type point_t = object(self)
method get_x : int
method with_x : int -> self
method move : int -> self
end;;
可以省略with_x
方法,如果你只允許通過move
方法更新。
對此的推理是,具有可變版本變量的類是具有相同變量的不可變版本的類的正確子類,因爲它具有相同的一組操作,再加上一個 - 能夠設置變量。因此,任何類型爲point_t
的抽象都可以應用於具有或不具有可變性的類實例(儘管它不能改變該變量)。請注意,相反是不可能的,如果您將類型point_t
定義爲可變x
,並且會嘗試使用不可變的實現它,那麼類型系統將會抱怨。由於您的實施不提供所有操作。
此外,有一件事情,你可能會錯過。儘管類point
具有可變變量x
,但該可變性實際上被類型約束point_t
密封(即隱藏)。所以,不管是什麼實現,接口被嚴格定義爲具有不可變x
:
class the_point = object
inherit point
method! move d = x <- x - d
end
method! move d = x <- x - d
^^^^^^^^^^
Error: The instance variable x is not mutable
你的混亂可能來自一個事實,即你有OOP,其中類類型構成了Java/C++風格的一些經驗出現名義上,而一個類只能通過顯式繼承成爲另一個類的子類。在OCaml中,一個類是另一個類的子類,如果它是一個語法超集,即它是否至少包含超類的所有字段。沒有必要從超類繼承,成爲它的子類。並且class point : point_t
不是繼承,而是一個類型約束,它表示:這裏是類表達式,它實現了point_t
類(也許更多),請確保它是真實的,並且只向外界暴露接口point_t
。
而最後一點,我已經明確表示長期子分級作爲句法超集超類的強調一個事實,即繼承和子類化並不意味着亞型。後者是語義(即實例的行爲),前者是語法,即一組代碼片段。子類化爲您提供了代碼重用,從超類複製代碼的能力(因爲inherit
實際上只是將超類的代碼複製/粘貼到您的子類)。子類型爲您提供了多態 - 可以在不同的實現上使用相同的抽象。
來源
2016-07-05 21:38:18
ivg
我覺得奇怪的是,val_x和val_point_t之間的權限沒有什麼區別,但我想這可能不是真的需要它。幾周前剛剛開始學習OCaml。謝謝 ! –
@ J-Lab有一個區別,我已經用這個行爲背後的推理更新了我的答案。希望它能幫助你。 – ivg