Still can be so:

Class dc.test Abstract ]
{

ClassMethod Test("#")
{
  "Test_",s
}

ClassMethod mac() [ ProcedureBlock = 0 ]
{
sub1(s=1)
  "sub1_",s
  q
sub2(s=2)
  "sub2_",s
  q
procPrivate(s=3) {
  "procPrivate_",s
}
procPublic(s=3) public {
  "procPublic_",s
}
}

}

Result:

USER>zTest^dc.test.1(1)
Test_1
USER>sub1^dc.test.1
sub1_1
USER>sub2^dc.test.1
sub2_2
USER>sub1^dc.test.1(10)
sub1_10
USER>sub2^dc.test.1(10)
sub2_10
USER>procPrivate^dc.test.1(10)
 
D procPrivate^dc.test.1(10)
^

USER>procPublic^dc.test.1(10)
procPublic_10
USER>

My best result is 77 72 69 67 so far.

Class ITPlanet.Task4 Abstract ]
{

ClassMethod main(As %Integer 10)
{
 x=1:1:y=1:1:w $c(y#s<2!$lf($lb(1,s,y,s-y+1),x)*3+32)
}

ClassMethod length(
  class = {$classname()},
  method "main"As %Integer CodeMode = expression ]
{
##class(%Dictionary.MethodDefinition).IDKEYOpen(classmethod).Implementation.Size
}

}

USER>##class(ITPlanet.Task4).length()
67
USER>##class(ITPlanet.Task4).main(11)

###########
##       ##
# #     # #
#  #   #  #
#   # #   #
#    #    #
#   # #   #
#  #   #  #
# #     # #
##       ##
###########

Make two changes to your code:

  1. /// return json
    Method infoJson() As %String WebMethod ]
    {
        set soapresponse=##class(webservice.SOAPResponse).%New()
        set soapresponse.CustomerID="1"
        set soapresponse.Name="2"
        set soapresponse.Street="3"
        set soapresponse.City="4"
        set soapresponse.State="5"
        set soapresponse.Zip="6"
    
        set stream=##class(%Stream.TmpBinary).%New()
        do ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(stream,soapresponse,,,$$$YES,"s")
        quit stream.Read($$$MaxStringLength)
    }
  2. /// write ##class(PRD.Test).test1()
    ClassMethod test1() As %String
    {
        set soapresponse=##class(webservice.SOAPResponse).%New()
        set soapresponse.CustomerID="1"
        set soapresponse.Name="2"
        set soapresponse.Street="3"
        set soapresponse.City="4"
        set soapresponse.State="5"
        set soapresponse.Zip="6"
        
        set stream=##class(%Stream.TmpBinary).%New()
        do ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(stream,soapresponse,,,$$$YES,"s")
        quit stream.Read($$$MaxStringLength)
    }

Fixed bugs/typos and added new types.

#include %PVA
types ; Show COS-Datatypes ; kav ; 2018-03-04
 array,i,bitstring
 
 s $bit(bitstring,1) = 1

 "№",?4,"VALUE",?30,"JSON",?45,"$LISTBUILD",!,$TR($J("",55)," ","-"),!
 
 array=[
          (bitstring),
          ($ZBITSET($ZBITSTR(4,1),2,0)),
          ($lb("")),
          null,
          true,
          false,
          (##class(%ZEN.proxyObject).%New()),
          [],
          {},
          "abcd",
          ($wc(35222)),
          "2",
          2,
          -2,
          2.1,
          -2.1,
          ($double(2.1))
          ]
 array."18"=2
 array."19"=-2
          
 i=0:1:array.%Size() {
   i,")",?4,array.%Get(i),?30,$$TypeOf1(.array,i),?45,$$TypeOf2(array.%Get(i)),!
 }
 
 // Return JSON datatype by the documented way
 //
TypeOf1(&array,key)
{
  typ=array.%GetTypeCodeOf(key)
  typ_" "_$case(typ,
    $$$PVVALUENULL:"null",
    $$$PVVALUETRUE:"boolTrue",
    $$$PVVALUEFALSE:"boolFalse",
    $$$PVVALUEINTEGERPOS:"+int",
    $$$PVVALUEINTEGERNEG:"-int",
    $$$PVVALUEUNUSED1:"unused",
    $$$PVVALUEARRAY:"array",
    $$$PVVALUEOBJECT:"object",
    $$$PVVALUETEXT:"text",
    $$$PVVALUENUMBER:"number",
    $$$PVVALUEOVERFLOW:"overflow",
    $$$PVVALUECACHENUMERIC:"cacheNumeric",
    $$$PVVALUEOREF:"oref",
    $$$PVVALUEUNASSIGNED:"unassigned",
    $$$PVVALUELONGPOS:"+long",
    $$$PVVALUELONGNEG:"-long",
    $$$PVVALUEBYTE:"byte[]",
    $$$PVVALUEDATETIME:"dateTime",
    $$$PVVALUEDOUBLE:"double",
    $$$PVVALUESINGLE:"single",
    $$$PVVALUEUTF8:"utf8",
    $$$PVVALUENESTED:"nested",
    $$$PVVALUEEOF:"eof",
    :"unknown")
}
   
 // Return datatype by the undocumented $LB() way
 //
TypeOf2(val)
 {
  i $l(val)>253 {
    typ=$ziswide(val)+1
  else {
    typ=$a($lb(val),2)
  }
  typ_" "_$case(typ
    ,1:"8bitString"
    ,2:"16bitString"
    ,4:"nonNegativeInteger"
    ,5:"negativeInteger"
    ,6:"nonNegativeFloat"
    ,7:"negativeFloat"
    ,8:"double"
    , :"??? never seen before")
}

Result:

USER>^types
№   VALUE                     JSON           $LISTBUILD
-------------------------------------------------------
0)  Ÿ                          8 text         1 8bitString
                              8 text         1 8bitString
2)                            8 text         1 8bitString
3)                            0 null         1 8bitString
4)  1                         1 boolTrue     1 8bitString
5)  0                         2 boolFalse    1 8bitString
6)  4@%ZEN.proxyObject        12 oref        1 8bitString
7)  2@%Library.DynamicArray   6 array        1 8bitString
8)  1@%Library.DynamicObject  7 object       1 8bitString
9)  abcd                      8 text         1 8bitString
10) 視                         8 text         2 16bitString
11) 2                         8 text         1 8bitString
12) 2                         9 number       4 nonNegativeInteger
13) -2                        9 number       5 negativeInteger
14) 2.1                       9 number       6 nonNegativeFloat
15) -2.1                      9 number       7 negativeFloat
16) 2.1000000000000000888     18 double      8 double
17)                           13 unassigned  1 8bitString
18) 2                         3 +int         4 nonNegativeInteger
19) -2                        4 -int         5 negativeInteger
20)                           31 eof         1 8bitString

On my desktop quite other results.

  N,j,time

  N=1e8

  j=1,2/*,3,4,5*/ {
    j,") "

    time=$zh
    d @("j"_j)(N)
    w $zh-time," s.",!
  }
  q
j1(N) public {
  i=1:1:{(a,b,c,d,e,f)=0}
}
j2(N) public {
  i=1:1:{a=0,b=0,c=0,d=0,e=0,f=0}
}
j3(N) public {
  i=1:1:{a=0,b=1,c=2,d=3,e=4,f=5}
}
j4(N) public {
  i=1:1:{a=0 b=1 c=2 d=3 e=4 f=5}
}
j5(N) public {
  i=1:1:{s $lb(a,b,c,d,e,f)=$lb(0,1,2,3,4,5)}
}

Results:

USER>^perf
1) 11.814189 s.
2) 4.683832 s.

As you can see the difference is almost 2.5 times.

Undefined variable and the variable contains "" (null) is two different situations, e.g. (see $DATA):

kill myObj
write $data(myObj),! ; -> 0
set myObj=$$$NULLOREF
write $data(myObj),! ; -> 1

In your case it would be better to use $IsObject:

kill myObj
write $IsObject(myObj),! ; -> 0
set d=$$$NULLOREF
write $IsObject(myObj),! ; -> 0
set myObj={}
write $IsObject(myObj),! ; -> 1

Accordingly, should be do $$$AssertTrue('$IsObject(myObj), "myObj is null")

You are right, the macro $$$NULL present only in %sqlMigration.inc and this is not the file that developers often include to its project.
I prefer to use the macro $$$NULLOREF/$$$NULLOID from %occExtent.inc, which is available by default in the class that inherits from %Library.Base, and for routines is enough to include %systemInclude.inc.

Why so difficult?
This similarly following condition:

WHERE 
(
year(current_date) - year(DOB)
) >= 13

It Besides above was already indicated, why does not follow to use such a code, for example:

select datediff(year,
todate(to_char({'1990-12-31'},'YYYY')||':1','YYYY:MM'), -- birthday
todate(to_char({'2003-01-01'},'YYYY')||':1','YYYY:MM') -- report date
)

This gives an incorrect result - 13, although it should be 12.

Then this:

Include Child

Class Macro.Child Extends Macro.Parent
{

ClassMethod first()
{
  #include Child
}

ClassMethod Test() [ PlaceAfter = first ]
{
  write "Class: " $classname() , ! , "Value: " $$$name
}

}

or this:

ClassMethod Test()
{
  #include Child
  write "Class: " $classname() , ! , "Value: " $$$name
}