Determining type on the fly in OCaml's OOP construct

本秂侑毒 提交于 2019-12-10 18:07:58

问题


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?


回答1:


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)



回答2:


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.




回答3:


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!



来源:https://stackoverflow.com/questions/633200/determining-type-on-the-fly-in-ocamls-oop-construct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!