在 OCaml 的 OOP 构造中动态确定类型

发布于 2024-07-14 15:37:04 字数 434 浏览 4 评论 0原文

我正在学习 OCaml 的 OOP 构造,并今天部分实现了这一点,直到我意识到我不知道如何在不使用对象外部的 type 关键字的情况下表示多态匹配语句。

class bar (param:string) =
object (code)

end;;

class foo param =
object (code)
 initializer 
  match param with
   string -> Printf.printf "param is a string"
   | bar -> Printf.printf "param is a bar"     
end;;

let b = new bar "a string";;
let f1 = new foo "test";;
let f2 = new foo b;;

是否可以确定动态传入的对象类型?

I am learning about OCaml's OOP constructs and partially implemented this today until I realized I have no idea how to represent a polymorphic match statement without using the type keyword outside of the object.

class bar (param:string) =
object (code)

end;;

class foo param =
object (code)
 initializer 
  match param with
   string -> Printf.printf "param is a string"
   | bar -> Printf.printf "param is a bar"     
end;;

let b = new bar "a string";;
let f1 = new foo "test";;
let f2 = new foo b;;

Is it possible to determine the type of object passed in on-the-fly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

但可醉心 2024-07-21 15:37:05

多态匹配语句的思想与面向对象编程的思想相矛盾! 行为的定制应该封装在对象中,这就是它们的用途。 询问类“你实际上是什么”的代码表明存在设计问题。

也就是说,如果您确实希望类能够告诉您它们实际上是什么,最简单的方法就是为此添加一个方法:

type typ = A | B

class bar =
object
  method typ = A
end

class rebar =
object
  method typ = B
end

class foo param =
object
   initializer
   match param#typ with
   | A -> print_endline "This is a A"
   | B -> print_endline "This is a B"
end

不要为此使用多态变体,因为您会破坏维护操作中详尽模式匹配的优势。

同样,如果您这样做,您可能会忽略里氏替换原则并为忙碌的日子做好准备您的代码的维护人员。 我们的世界不需要那样的残酷!

The idea of a polymorphic match statement contradicts the very idea of object-oriented programming! Customisation of behaviour should be encapsulated in objects, this is what they are for. Code asking a class “what are you, actually” signals a design problem.

That said, if you really want classes to be able to tell you what they actually are, the easiest way is to just add a method for this:

type typ = A | B

class bar =
object
  method typ = A
end

class rebar =
object
  method typ = B
end

class foo param =
object
   initializer
   match param#typ with
   | A -> print_endline "This is a A"
   | B -> print_endline "This is a B"
end

Do not use polymorphic variants for this, as you break the advantage of exhaustive pattern matchings in maintenance operations.

Again, if you do so, you are likely ignoring the Liskov substitution principle and preparing busy days for the maintenance officer of your code. Our world does not need that cruelty!

意中人 2024-07-21 15:37:04

该匹配除了将 'param' 绑定到 'string' 之外没有做任何事情,ocaml 应该说没有使用第二个匹配。 我相信您必须使用变体类型来进行匹配。 下面是使用多态变体类型的示例。

class bar (param:string) =
  object (code)
end

class foo param =
  object (code)
  initializer 
    match param with
    | `String str -> Printf.printf "param is a string"
    | `Bar bar -> Printf.printf "param is a bar"     
end

let b = new bar "a string"
let f1 = new foo (`String "test")
let f2 = new foo (`Bar b)

That match isn't doing anything but binding 'param' to 'string', ocaml should say that the second match isn't used. I believe you'll have to use variant types to do the matching. Below is an example using polymorphic variant types.

class bar (param:string) =
  object (code)
end

class foo param =
  object (code)
  initializer 
    match param with
    | `String str -> Printf.printf "param is a string"
    | `Bar bar -> Printf.printf "param is a bar"     
end

let b = new bar "a string"
let f1 = new foo (`String "test")
let f2 = new foo (`Bar b)
风筝在阴天搁浅。 2024-07-21 15:37:04

一般来说,OCaml 不支持运行时类型识别。

也就是说,运行时表示中嵌入了一些类型信息,以便垃圾收集器工作。 要确定某物是否是字符串,您可以执行以下操作:

if Obj.tag (Obj.repr param) = Obj.string_tag then

有关 OCaml 运行时表示的更多信息,请参阅 C 与 Objective Caml 的接口。 然而,这些类型的检查通常与 OCaml 鼓励的编程类型背道而驰,并且不清楚如何使用此特定检查做任何有用的事情(您需要转换为字符串,并且对类型造成严重破坏)安全)。 更好的解决方案是使用代数数据类型或多态变体来描述有效的参数类型和模式匹配。

类型安全向下转型可能很有用,但 OCaml 确实不支持。 如果您正在寻找的话,您将需要推出自己的机制(或者更好的是,围绕它进行设计)。

In general, OCaml does not support run-time identification of types.

That said, there is a little type information embedded in the runtime representation to let the garbage collector work. To determine if something is a string, you can do:

if Obj.tag (Obj.repr param) = Obj.string_tag then

More information on OCaml's runtime representation is available in Interfacing C with Objective Caml. However, these kinds of checks generally run counter to the the kinds of programming OCaml encourages, and it is not clear how you would do anything useful with this particular check (you'll need to convert to a string, and are wreaking havoc on type safety). A far better solution is to use an algebraic data type or polymorphic variants to describe the valid parameter types and pattern-match over that.

Type-safe downcasts could be useful but indeed are not supported by OCaml. You'll need to roll your own mechanism (or, better, design around it) if that is what you are looking for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文