Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>EDIT - Separated the answer in 3 main points: the resolution of the initial compile error, a recursive solution, and a parametrized solution</p> <p><strong>Resolution of the compile error</strong></p> <p>Note that your code works fine in the top level:</p> <pre><code># let s = new salesman ();; val s : &lt; visitSalesman : 'a -&gt; unit; _.. &gt; salesman as 'a = &lt;obj&gt; </code></pre> <p>This kind of compile error is generally solved by adding a type annotation to help the compiler figuring the type. As the top level kindly told us what it was, we can modify the instantiation:</p> <pre><code>let s : (&lt; visitSalesman : 'a -&gt; unit&gt;) salesman = new salesman ();; </code></pre> <p>And this compiles!</p> <p><strong>A recursive solution</strong></p> <p>It is possible to reduce complexity by using recursive classes. This totally removes the need for parametrized classes, but means that all objects need to be defined in the same source file.</p> <pre><code>class virtual employee = object method virtual receiveEvaluation:(hrrep -&gt; unit) end and accountant = object(self) inherit employee method receiveEvaluation:(hrrep -&gt; unit) = fun rep -&gt; rep#visitAccountant (self :&gt; accountant) end and salesman = object (self) inherit employee method receiveEvaluation:(hrrep -&gt; unit) = fun rep -&gt; rep#visitSalesman (self :&gt; salesman) end and hrrep = object method visitSalesman:(salesman -&gt; unit) = fun s -&gt; print_endline ("Visiting salesman") method visitAccountant:(accountant -&gt; unit) = fun s -&gt; print_endline ("Visiting accountant") end let s = new salesman;; let e = (s :&gt; employee);; let v = new hrrep;; e#receiveEvaluation v;; </code></pre> <p>This prints "Visiting salesman". The coercion to employee is just to make this closer to a real world scenario.</p> <p><strong>A parametrized solution</strong></p> <p>Looking at the problem again, I think it is not necessary to have a parametrized hrRep, because at this moment, all other types are known. By just making the employee class parametrized, I get this:</p> <pre><code>class virtual ['a] employee = object method virtual receiveEvaluation : 'a -&gt; 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 -&gt; unit method virtual visitSalesman : hrRep salesman -&gt; 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;; </code></pre> <p>This returns:</p> <p>Visiting salesman S Bob</p> <p>Visiting accountant A Mary</p> <p>Visiting salesman S Sue</p> <p>The advantage of this solution is that employees do not need to know about the visitor, and therefore can be defined in their own compilation units, leading to cleaner code and less recompilation to do when adding new types of employees.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload