A more object-oriented approach may be helpful here. For example:
BeginPackage["example`"]; thing; new; Begin["`Private`"]; thing /: new[thing[contents_]] := Module[{thing}, (* Supported operations: *) thing /: Plus[thing[x_], y_] := thing[x + y]; thing /: Times[thing[x_], y_] := thing[x y]; (* Example invalid operation: *) thing /: Power[_thing, _] := $Failed; (* Format value: *) thing /: Format[thingMakeBoxes[thing, StandardForm] = Interpretation[ToExpression["example`thing"]InterpretationBox["thing", thing]; (* Return symbol: *) thing[contents] ]; End[]; EndPackage[]; Now we can write, e.g,
myThing = new@thing[73]; 4 myThing + 3 which gives:
thing[295] (* == thing[4 * 73 + 3] *) However, despite the displaystandard form (which can also be copied and pasted from output to input thanks to the InterpretationInterpretationBox), the internal representation is quite different:
% // InputForm (* -> thing$576[295] *) As a result we can't just conjurconjure things up without invoking new, as the methods defined on real things simply won't exist in that case:
myNewThing = thing[48]; myNewThing + 17 (* 17 + thing[48] *) Strictly speaking, the format value would have been enough to answer your question as stated. However, it seems like an object oriented approach is quite a natural fit for what you're probably trying to achieve here, so the extra effort may be worthwhile for maintainability and robustness reasons if you intend to have a lot of different objects each with their own private methods and/or internal state.