Hi,
How do you enforce abstract methods? For example:
Class Foo Foo abstract instproc procdef args
Class Bar -superclass Bar instproc proc2
Bar barObj
I would like an error to be thrown at the "Bar barObj" line because the Bar object doesn't define the procdef instproc. Is this rule enforceable? Is my only way at it to use assertions?
Thanks,
L
"LD" == Laurent Duperval laurent.duperval@netergynet.com writes:
LD> Hi, LD> How do you enforce abstract methods? For example:
LD> Class Foo LD> Foo abstract instproc procdef args
LD> Class Bar -superclass LD> Bar instproc proc2
LD> Bar barObj
LD> I would like an error to be thrown at the "Bar barObj" line because the Bar LD> object doesn't define the procdef instproc. Is this rule enforceable? Is my LD> only way at it to use assertions?
there are two answers:
1. there are many ways to this in XOTcl ... Yes, assertions are one of them. Filters are another one. You can intercept every call to "abstract" and store all abstract procs/instprocs. Then you check all of them for every call. Obviously this is horrible to performance. Therefore assertions might be better here, because their concept is to be turned off in the final version ... you only check for debugging.
XOTcl is intented as an extensible language. The abstract method is defined in predefined.xotcl:
Object instproc abstract {methtype methname arglist} { if {$methtype != "proc" && $methtype != "instproc"} { error "invalid method type '$methtype', \ must be either 'proc' or 'instproc'." } [self] $methtype $methname $arglist \ [list error "Abstract method $methname $arglist called"] }
Here, the definition is quite simplistic. If you require a different behavior you can implement an extended version (e.g. with an instmixin on Object) ... if you also extend "create" you can check that never an instance is created, which has an abstract, unspecialized method. Just to show how this could work:
Class EnforceAbstract EnforceAbstract instproc abstract {methtype methname arglist} { [self] lappend __abstractMethods $methname next } EnforceAbstract instproc create args { set obj [next] set class [$obj info class] foreach c [concat $class [$class info heritage]] { if {[$c exists __abstractMethods]} { foreach abstractProc [$c set __abstractMethods] { set implCl [$obj procsearch $abstractProc] if {"$implCl" == "::XOTclClasses${c}::$abstractProc"} { error "Abstract Method not specialized: $c->$abstractProc for $obj" } } } } return $obj } Object instmixin EnforceAbstract
now your example produces the intended error message
2. However, the simple implementation of "abstract" is not chosen without reason: We have not intended "abstract" as a constraint for programming, but as a way to document interfaces. E.g. a documentation tool may extract these information. And a programmer knows that it is her/his responsiblity to implement the method. This is a different philosophy than in languages, like Java, where everything is statically checked. However, then you have to live with a far more rigid language. The XOTcl philosophy is to constraint only what is absolutely necessary and that the programmer can extend constraining mechanisms easily (as above). So you can customize the language to the context of your problem. E.g. if you never use a part of an interface, you don't have to specialize it at all. But if you require that to be ensured ... you can do that.
btw, I'm not sure that checking when the instance is created is the best choice in the general case, because in XOTcl you're allowed to build object-specific procs, e.g.:
Object instmixin EnforceAbstract Class Foo Foo abstract instproc procdef args
Class Bar -superclass Foo #Bar instproc procdef {} {..} Bar create barObj barObj proc procdef args {puts "I'm a valid implementation"}
Here, the checking would report an error even though we have an implementation that conforms to the abstract interface.
Regards,
Uwe