Make a custom object look like MatrixForm of a matrix?

InterpretationBox will take care of making safe round trip from boxes to expression but we need to take extra care during condition checking and partition not to evaluate Obj's arguments.

It does not matter that Obj is not holding them, Obj itself can be held. Hold @ Obj[1,2,3,4] etc.

Edit to the old code

As xzczd has noticed, an Input cell with e.g. Obj[1,2,3,4] shows explicit MatrixForm after Ctrl+Shit+N.

Which is strange, the more that I can't reproduce that with combinations of NotebookRead/MakeExpression/MakeBoxes etc.

The problem seems to be caused by TagBox so we can take even more extra care and work around it:

Obj /: MakeBoxes[ 
  o : Obj[args__], StandardForm
] /; IntegerQ @ Sqrt @ Length @ Unevaluated @ args := With[
  { array = (
      List @@@ Partition[Hold[args], Sqrt@Length[Unevaluated[args]]]
    ) /. Hold[lists__] :> Map[
      Function[x, MakeBoxes[x, StandardForm], HoldFirst]
    , Unevaluated @ {lists}
    , {2}
    ]
  }
, InterpretationBox[
    RowBox[{ "(", "\[NoBreak]"
    , GridBox[array, RowSpacings -> 1, ColumnSpacings -> 1
      , RowAlignments -> Baseline, ColumnAlignments -> Center
      ]
    , "\[NoBreak]", ")"
    }]
  , o
  ]
]

Old

Obj /: MakeBoxes[
  o : Obj[args__], StandardForm
] /; IntegerQ @ Sqrt @ Length[Unevaluated[args]] := With[
  { matrixFormBoxes = (
      List @@@ Partition[Hold[args], Sqrt @ Length[Unevaluated[args]]]
    ) /. Hold[lists__] :> MakeBoxes[MatrixForm[{lists}]]
  }
, InterpretationBox[
    matrixFormBoxes
  , o
  ]
]

Obj[1, 2, 3, 4]
Obj[1, 2, 4]
Hold @ Obj[Echo[1], 2, 3, 4, 5, 6, 7, 8, 9]

enter image description here

% // ReleaseHold

enter image description here

% // FullForm
Obj[1,2,3,4,5,6,7,8,9]

related:

https://mathematica.stackexchange.com/a/149668/5478


InterpretationBox used in answer by J.M. and by Kuba allows you to copy formatted object and keep its proper interpretation as an Obj expression, but you can't edit such formatted objects. You could make InterpretationBox editable by using Editable -> True option but this will allow you to just edit formatted version while interpretation would incorrectly remain unchanged.

To make copied formatted object editable, instead of InterpretationBox, you could use TemplateBox with appropriate DisplayFunction:

Obj // ClearAll
Obj /: MakeBoxes[Obj@args__, StandardForm] := Module[{n, k}, 
    n = Length@Unevaluated@args;
    k = Sqrt@n;
    TemplateBox[
        MakeBoxes /@ Unevaluated@{args},
        "Obj",
        Tooltip -> "Obj",
        DisplayFunction -> (Evaluate@RowBox@{"(", "\[NoBreak]", GridBox[
            Partition[Array[Slot, n], k],
            RowSpacings -> 1, ColumnSpacings -> 1,
            RowAlignments -> Baseline, ColumnAlignments -> Center
        ], "\[NoBreak]", ")"}&)
    ] /; IntegerQ@k
]

Example of copying and editing of formatted object:

Obj[1, 2, 3, 4]

Obj copying and editing


Something to start with:

Obj /: MakeBoxes[Obj[args__], form : StandardForm] := 
       With[{arr = Partition[{args}, Sqrt[Length[{args}]]]}, 
            With[{boxes = MakeBoxes[MatrixForm[arr], form]}, 
                 InterpretationBox[boxes, Obj[args]]]]

I make no attempt to check if the number of arguments is a square number; you can add that check yourself, if you wish.