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.
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.
Comment