2016-04-05 52 views
2

我面臨一個問題,研究OCaml文檔並沒有使我找到一個令人滿意的解決方案。OCaml封裝

下面的代碼片段說明我的問題:

class A = object (self) 
    (* this should not be overwrittable in subclass B, but callable 
     on objects of type B! 
    *) 
    method dangerous_one input = 
     (do dangerous stuff...) 
     let safe_output = safe_dangerous_one input in 
     (... more dangerous things done with safe_output ...) 

    (* This is safe, should be overwrittable and callable in subclass *) 
    method safe_dangerous_one input = (...) 
end 

class B = object(self) inherit A as super 
    method! safe_dangerous_one input = (* subclass behaviour ... *) 
end 

綜上所述片斷:A類是基類的子類B. 它有一個危險的方法,它是複雜的,有一些陰暗的角落我不不希望客戶端代碼必須處理。事實上,我想禁止覆蓋方法「dangerous_one」的子類。

相反,它們應該覆蓋函數「safe_dangerous_one」。

此外,應該是可能的,其中「B:B」來稱呼「B#dangerous_one」作爲類B.指定一個使用「safe_dangerous」 - 零件的(新的)定義

出現我的兩難如果我只是簡單地將方法「dangerous_one」設置爲private,那麼沒有任何東西讓B類中的客戶端代碼覆蓋它,甚至可能會公開它。

如果我將其實現從簽名中隱藏起來,它不能再被覆蓋,但我不能再調用「b#dangerous_one」 - 代碼也無法被調用。

有什麼辦法可以實現我的目標嗎?

最佳, Nablezen

回答

2

如果我隱藏簽名的執行,不能再被改寫,但我不能叫「B#dangerous_one」了 - 該代碼將無法訪問到電話也。

你可以,你只需要讓它private,你不能隱藏public方法:

class type safe = object 
    method safe_dangerous_one : in_channel -> int 
    end 

    class a : safe = object (self) 
    method private dangerous_one input = input_binary_int input 
    method safe_dangerous_one input = 
     max 255 (self#dangerous_one input) 
    end 

    class b parameters = object(self) 
    inherit a parameters as super 
    method! safe_dangerous_one input = 
     super#safe_dangerous_one input + 1 
    end 

如果你想unsafe方法可訪問,但不可重寫,然後就重新發布它在另一個名字(種類NVI):

class type safe = object 
    method unsafe_dangerous_one : in_channel -> int 
    method safe_dangerous_one : in_channel -> int 
    end 

    class a : safe = object (self) 
    method private dangerous_one input = input_binary_int input 
    method unsafe_dangerous_one input = self#dangerous_one input 
    method safe_dangerous_one input = 
     max 255 (self#dangerous_one input) 
    end 

    class b = object(self) 
    inherit a as super 
    method! safe_dangerous_one input = 
     super#safe_dangerous_one input + 1 
    end 

而且一個免費的建議。在其他語言中,類和方法被用作構建程序的工具,因爲它們沒有更好的工具。在OCaml中,您擁有一流的功能,記錄,結構等。因此,最好在每種情況下使用適當的工具。當你設計一個類時,你應該明白,它的原始定義(不會被C++/Java/Python /等破壞)是可以覆蓋的。一種方法是一種操作,其實現在一些屬中有所不同。所以,如果你將某些東西定義爲一種方法,然後努力防止人們重寫它,那麼你做錯事的可能性很高。如果你不希望它被覆蓋,那麼就不要把它定義爲一種方法。在你的情況下,你應該把dangerous_one操作放入一個let-bound函數中。您可以在類的上下文的約束,所以,你將不得不對所有參數的訪問,還是可以綁定它放在頂層,選擇是你的:

class a parameters = 
    let dangerous_one input = input_binary_int input in 
    object (self) 
     method safe_dangerous_one input = 
     max 255 (dangerous_one input) 
    end 

    class b = object(self) 
    inherit a as super 
    method! safe_dangerous_one input = 
     super#safe_dangerous_one input + 1 
    end 

此外,一個非常好的來源關於OCaml類系統的文檔是Jason Hickey's Introduction to Objective Caml。它稍顯過時,但仍然非常好。

+0

「你可以,你只需要把它變成私人的,你不能隱藏公共方法」 嗯,是的,我覺得我的意思是我必須把它變成私人的,當它是私人的時候,方法不可能是再次呼籲對象..例如「b#unsafe_dangerous」將不起作用,因爲現在不安全的方法是私人的。 – Nablezen

+0

當然,然後將其設爲私人並以其他名稱重新發布,正如我在第二個示例中所建議的那樣。 – ivg