我正在学习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;;
是否可以确定即时传递的对象类型?
答案 0 :(得分:3)
除了将'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)
答案 1 :(得分:2)
通常,OCaml不支持类型的运行时识别。
也就是说,在运行时表示中嵌入了一些类型信息以使垃圾收集器工作。要确定某些字符串是否为字符串,您可以执行以下操作:
if Obj.tag (Obj.repr param) = Obj.string_tag then
有关OCaml运行时表示的更多信息,请参见Interfacing C with Objective Caml。但是,这些类型的检查通常与OCaml鼓励的编程类型背道而驰,并且不清楚如何使用此特定检查执行任何有用的操作(您需要转换为字符串,并且会对类型造成严重破坏)安全)。一个更好的解决方案是使用代数数据类型或多态变体来描述有效的参数类型和模式匹配。
类型安全的向下转换可能很有用,但OCaml确实不支持。如果你正在寻找的话,你需要推出自己的机制(或者更好的是围绕它设计)。
答案 2 :(得分:0)
多态匹配语句的想法与面向对象编程的想法相矛盾!行为的定制应该封装在对象中,这就是它们的用途。代码要求一个类“实际上你是什么”表示设计问题。
那就是说,如果你真的希望类能够告诉你它们实际上是什么,最简单的方法就是为此添加一个方法:
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
不要使用多态变体,因为您在维护操作中打破了详尽模式匹配的优势。
同样,如果您这样做,您可能会忽略Liskov substitution principle并为代码的维护人员准备繁忙的日子。我们的世界不需要那种残忍!