Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns OCaml中的访问者设计模式_Design Patterns_Ocaml_Visitor - Fatal编程技术网

Design patterns OCaml中的访问者设计模式

Design patterns OCaml中的访问者设计模式,design-patterns,ocaml,visitor,Design Patterns,Ocaml,Visitor,我试图使用OCaml的OO构造和类型系统实现访问者设计模式,但在实例化元素时遇到了问题 class virtual ['hrRep] employee = object method virtual receiveEvaluation : 'hrRep -> unit method virtual getName : string end;; class ['hrRep] accountant myName = object (self : 'a) inherit ['hrRep

我试图使用OCaml的OO构造和类型系统实现访问者设计模式,但在实例化元素时遇到了问题

class virtual ['hrRep] employee = object 
 method virtual receiveEvaluation : 'hrRep -> unit
 method virtual getName : string
end;;

class ['hrRep] accountant myName = object (self : 'a)
 inherit ['hrRep]employee
 val name = myName
 method receiveEvaluation rep = rep#visitAccountant self
 method getName = name
end;;

class ['hrRep] salesman myName = object (self : 'a)
 inherit ['hrRep]employee
 val name = myName
 method receiveEvaluation rep = rep#visitSalesman self
 method getName = name
end;;

class virtual ['accountant, 'salesman] hrRep = object (self)
 method virtual visitSalesman : 'salesman -> unit
 method virtual visitAccountant : 'accountant -> unit
end;;

class ['employee, 'salesman] lowerLevelHRRep = 
      object (self) inherit ['employee, 'salesman]hrRep
 method visitSalesman s = print_endline ("Visiting salesman "^s#getName)
 method visitAccountant a = 
       print_endline ("Visiting accountant "^a#getName)
end;;

let s1 : (<visitSalesman : 'a -> unit>) salesman = new salesman "Bob";;
let a1 : (<visitAccountant : 'a -> unit>) accountant = new accountant "Mary";;
let s2 : (<visitSalesman : 'a -> unit>) salesman = new salesman "Sue";;
let h1 : (<getName : string>, <getName : string>) lowerLevelHRRep = new lowerLevelHRRep;;

s1#receiveEvaluation h1;;

第二种对象类型没有方法
visitAccountant

编辑-将答案分为三个要点:初始编译错误的解决方案、递归解决方案和参数化解决方案

编译错误的解决方法

请注意,您的代码在顶层运行良好:

# let s = new salesman ();;
val s : < visitSalesman : 'a -> unit; _.. > salesman as 'a = <obj>
这是“拜访推销员”的照片。对员工的强制只是为了使其更接近真实世界的场景

参数化解决方案

再看看这个问题,我认为没有必要使用参数化的hrRep,因为目前,所有其他类型都是已知的。通过将employee类参数化,我得到了以下结果:

class virtual ['a] employee = 
object
  method virtual receiveEvaluation : 'a -> unit
  method virtual getName : string
end

class ['a] accountant name =
object(self)
  inherit ['a] employee
  val name = name
  method receiveEvaluation rep = rep#visitAccountant self
  method getName = "A " ^ name
end

class ['a] salesman name =
object(self)
  inherit ['a] employee
  val name = name
  method receiveEvaluation rep = rep#visitSalesman self
  method getName = "S " ^ name
end

class virtual hrRep = 
object
  method virtual visitAccountant : hrRep accountant -> unit
  method virtual visitSalesman : hrRep salesman -> unit
end

class lowerLevelHRRep =
object
  inherit hrRep
  method visitAccountant a = print_endline ("Visiting accountant " ^ a#getName)
  method visitSalesman s = print_endline ("Visiting salesman " ^ s#getName)
end;;

let bob = new salesman "Bob";;
let mary = new accountant "Mary";;
let sue = new salesman "Sue";;
let h = new lowerLevelHRRep;;
bob#receiveEvaluation h;;
mary#receiveEvaluation h;;
sue#receiveEvaluation h;;
这将返回:

来访推销员鲍勃

玛丽的来访会计师

拜访推销员苏


此解决方案的优点是,员工不需要了解访问者,因此可以在他们自己的编译单元中定义,从而在添加新类型的员工时,代码更干净,重新编译更少。

这似乎解决了编译问题,但当我试图通过调用saller对象中的函数进行编译时,我得到了一个类似的结果。如何调用该函数?再次感谢!我不确定我是否理解这个问题,你能发布一些代码吗?此外,我还添加了一个使用递归定义的更简单(尽管有限)的解决方案。希望有帮助!您的解决方案要优雅得多,可以完成同样的任务。如果您认为有办法完成我在修订版中提出的要求,我已经更新了原始问题中的代码。这些问题可能是由于hrRep的参数化,我只在员工身上发布了一个参数化解决方案,似乎可以做到这一点。
# let s = new salesman ();;
val s : < visitSalesman : 'a -> unit; _.. > salesman as 'a = <obj>
let s : (< visitSalesman : 'a -> unit>) salesman = new salesman ();;
class virtual employee =
object
  method virtual receiveEvaluation:(hrrep -> unit)
end

and accountant = 
object(self)
  inherit employee
  method receiveEvaluation:(hrrep -> unit) = fun rep -> rep#visitAccountant (self :> accountant)
end

and salesman = 
object (self)
  inherit employee
  method receiveEvaluation:(hrrep -> unit) = fun rep -> rep#visitSalesman (self :> salesman)
end

and hrrep = 
object
  method visitSalesman:(salesman -> unit) = fun s -> print_endline ("Visiting salesman")
  method visitAccountant:(accountant -> unit) = fun s -> print_endline ("Visiting accountant")
end

let s = new salesman;;
let e = (s :> employee);;
let v = new hrrep;;

e#receiveEvaluation v;;
class virtual ['a] employee = 
object
  method virtual receiveEvaluation : 'a -> unit
  method virtual getName : string
end

class ['a] accountant name =
object(self)
  inherit ['a] employee
  val name = name
  method receiveEvaluation rep = rep#visitAccountant self
  method getName = "A " ^ name
end

class ['a] salesman name =
object(self)
  inherit ['a] employee
  val name = name
  method receiveEvaluation rep = rep#visitSalesman self
  method getName = "S " ^ name
end

class virtual hrRep = 
object
  method virtual visitAccountant : hrRep accountant -> unit
  method virtual visitSalesman : hrRep salesman -> unit
end

class lowerLevelHRRep =
object
  inherit hrRep
  method visitAccountant a = print_endline ("Visiting accountant " ^ a#getName)
  method visitSalesman s = print_endline ("Visiting salesman " ^ s#getName)
end;;

let bob = new salesman "Bob";;
let mary = new accountant "Mary";;
let sue = new salesman "Sue";;
let h = new lowerLevelHRRep;;
bob#receiveEvaluation h;;
mary#receiveEvaluation h;;
sue#receiveEvaluation h;;