I'm not an expert on OOP, and the other answer in the Q&A the OP linked discusses some limitations of trying to emulate OOP in Mathematica. But, throwing caution to the wind, when I've done it, I take a modified approach. The basic object has the form class[dataVariable]
, where class
is HoldFirst
or HoldAll
and identifies the class of the object and dataVariable
is a symbol whose ownvalues define the characteristics of the object. Usually the dataVariable
is generated by Unique
or Module
in a private context. To make the output look nice, I usually define an output format for it (I'm not particularly expert at that, either).
Here's a minimal modification to show the idea:
circle // ClearAll;
circle // Attributes = {HoldFirst};
circle /: new[circle, center_, radius_] := (* instantiation *)
Module[{circle`data}, (* symbol in circle` context *)
circle`data = {center, radius};
circle[circle`data]
];
circle /: getSize[c_circle] := c[[1]][[2]]; (* NOT c[[1, 2]]! *)
circle /: setSize[c : circle[data_], size_] :=
(data[[2]] = size; c); (* returns the circle[] *)
(* formatting *)
validCircleQ[c_, test_ : (True &)] :=
MatchQ[c, circle[_Symbol]] &&
MatchQ[First[c], {{_?test, _?test}, _?test}];
MakeBoxes[e : circle[c_]?validCircleQ, StandardForm] :=
Replace[c, {p_,
r_} :> (InterpretationBox[#, e] &[
RowBox[{"circle", "[",
RowBox[{MakeBoxes[p], ",", MakeBoxes[r]}], "]"}]
])
];
Examples:
circ = new[circle, {2, 3}, 23]
(* circle[{2, 3}, 23] *)
% // FullForm
(* circle[circle`data$85563] *)
% // First
(* {{2, 3}, 23} *)
setSize[circ, 50]
(* circle[{2, 3}, 50] *)
% // First
(* {{2, 3}, 50} *)
getSize[circ]
(* 50 *)
For data
, I usually use associations. It's nice to have words tagging the data components, and the order does not matter in an Association
. In this case it could be the following:
circle`data = <|"Position" -> center, "Size" -> radius|>
One could then look up characteristics of an object with this:
circle /: get[circle[data_], args__] := Lookup[data, args]
get[circ, "Size"]
As I said, I'm not an expert on OOP, but I know there are important aspects of OOP such as inheritance and so forth. Don't ask me about them. I don't know how to do inheritance in a pleasant way. Maybe not in anyway. If you like OOP without inheritance, basically just object and methods, then the above is a good start.