This is occasioned by a thread begun by Alfonso Sánchez-Peñalver here.

It’s been a while since I’ve last waded into Mata’s class programming, but I don’t recall its behaving like that illustrated below. A standalone Mata function respects the type of an object, but that same function, when incorporated into a Mata class as a member function (method), does not.

.ÿ
.ÿversionÿ16.1

.ÿ
.ÿlogÿcloseÿ_all

.ÿlogÿusingÿInconsistentBehavior.smcl,ÿnomsgÿname(lo)

.ÿ
.ÿclearÿ*

.ÿ
.ÿlocalÿline_sizeÿ`c(linesize)'

.ÿsetÿlinesizeÿ80

.ÿ
.ÿmata:
-------------------------------------------------ÿmataÿ(typeÿendÿtoÿexit)ÿ------
:ÿmataÿsetÿmatastrictÿon

:ÿ
:ÿclassÿParentÿ{
>ÿÿÿÿÿÿÿÿÿpublic:
>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿvirtualÿvoidÿprobe()
>ÿ}

:ÿvoidÿfunctionÿParent::probe()ÿprintf("Parent\n")

:ÿ
:ÿclassÿChildÿextendsÿParentÿ{
>ÿÿÿÿÿÿÿÿÿpublic:
>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿfinalÿvoidÿprobe()
>ÿ}

:ÿvoidÿfunctionÿChild::probe()ÿprintf("Child\n")

:ÿ
:ÿclassÿSimpleFactoryÿ{
>ÿÿÿÿÿÿÿÿÿpublic:
>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿclassÿParentÿscalarÿcreate()
>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿclassÿParentÿscalarÿpassthrough()
>ÿ}

:ÿclassÿParentÿscalarÿfunctionÿSimpleFactory::create()ÿreturn(Child())

:ÿclassÿParentÿscalarÿfunctionÿSimpleFactory::passthrough(classÿParentÿscalarÿp)
>ÿÿÿÿÿreturn(p)

:ÿ
:ÿ//ÿNakedÿfunctions--identicalÿtoÿclassÿmemberÿfunctionsÿ(methods)ÿabove
:ÿclassÿParentÿscalarÿfunctionÿcreate()ÿreturn(Child())

:ÿclassÿParentÿscalarÿfunctionÿpassthrough(classÿParentÿscalarÿp)ÿreturn(p)

:ÿ
:ÿ//ÿDemonstrationÿofÿinconsistency
:ÿvoidÿfunctionÿtestClassMethods()ÿ{
>ÿÿÿÿÿÿÿÿÿclassÿSimpleFactoryÿscalarÿf
>ÿÿÿÿÿÿÿÿÿclassÿParentÿscalarÿp
>ÿ"1"
>ÿÿÿÿÿÿÿÿÿpÿ=ÿf.create()
>ÿÿÿÿÿÿÿÿÿp.probe()
>ÿ"2"
>ÿÿÿÿÿÿÿÿÿpÿ=ÿf.passthrough(Child())
>ÿÿÿÿÿÿÿÿÿp.probe()
>ÿ}

:ÿ
:ÿvoidÿfunctionÿtestNakedFunctions()ÿ{
>ÿÿÿÿÿÿÿÿÿ/*ÿclassÿSimpleFactoryÿscalarÿfÿ*/
>ÿÿÿÿÿÿÿÿÿclassÿParentÿscalarÿp
>ÿ"3"
>ÿÿÿÿÿÿÿÿÿpÿ=ÿ/*ÿf.ÿ*/ÿcreate()
>ÿÿÿÿÿÿÿÿÿp.probe()
>ÿ"4"
>ÿÿÿÿÿÿÿÿÿpÿ=ÿ/*ÿf.ÿ*/ÿpassthrough(Child())
>ÿÿÿÿÿÿÿÿÿp.probe()
>ÿ}

:ÿ
:ÿtestClassMethods()
ÿÿ1
Parent
ÿÿ2
Parent

:ÿ
:ÿtestNakedFunctions()
ÿÿ3
Child
ÿÿ4
Child

:ÿ
:ÿend
--------------------------------------------------------------------------------

.ÿ
.ÿsetÿlinesizeÿ`line_size'

.ÿ
.ÿquietlyÿlogÿcloseÿlo

.ÿ
.ÿexit

endÿofÿdo-file


.


Am I overlooking something here? If not, then this strikes me not only as inconsistent behavior, but also as a serious violation of the object-oriented programming principle of polymorphism. I suppose I could work around this by explicitly using pointers to the objects, but it seems like it ought not to be necessary to jump through such hoops inasmuch as a variable for an instantiated object I thought is already a pointer in disguise.

I’ve attached both the do-file and resulting log file for anyone interested.