2016-04-05 53 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