oop - OCaml封装

标签 oop ocaml encapsulation

我遇到了一个问题,研究 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#dangerous_one”,其中“b : B”,它使用 B 类中指定的“safe_dangerous”部分的(新)定义。

我的困境似乎是:如果我只是将方法“dangerous_one”设为私有(private),则没有什么可以阻止 B 类中的客户端代码覆盖它,甚至可能将其公开。

如果我从签名中隐藏它的实现,它就不能再被覆盖,但我不能再调用“b#dangerous_one” - 代码也变得无法调用。

有什么办法可以实现我的目标吗?

最好, 纳 bool 曾

最佳答案

If I hide its implementation from the signature, it can not be overwritten anymore, but I cannot call "b#dangerous_one" anymore - the code becomes inaccessible to calls also.

可以,只需将其设为私有(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/etc 破坏)是可以重写的。方法是一种操作,其实现在某些属中有所不同。因此,如果您将某些东西定义为一种方法,然后努力阻止人们覆盖它,那么您很可能做错了什么。如果您不希望它被重写,那么就根本不要将其定义为方法。在您的情况下,您应该将 dangerous_one 操作放入 let 绑定(bind)函数中。您可以将其绑定(bind)在类的上下文中,以便您可以访问所有参数,也可以将其绑定(bind)在顶层,选择权在于您:

  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 。虽然有点过时,但仍然非常好。

关于oop - OCaml封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36423626/

相关文章:

objective-c - Obj C - 理解指针

pattern-matching - 通过功能组合来统一OCaml模式

java - 如何重构内部类MouseAdapter?

c# - 从封装类传递事件

ruby - "public"、 "private"和 "protected"方法究竟做了什么?

Python - 组合类的继承

javascript - JQuery 插件类不工作

c++ - 定义类 X 的析构函数,它继承自指向对象 Y 的指针 vector 并具有指向 Z 的指针数组

ocaml - "constructors"的 OCaml 命名约定是什么?

c++ - 使用 swig 到 ocaml 的奇怪重命名行为