View · Search · Index
No registered users in community xowiki
in last 10 minutes

[Xotcl] Re: [Xotcl] Abstract class question

From: <uwe.zdun_at_uni-essen.de>
Date: Mon, 11 Dec 2000 17:35:15 +0100 (CET)

>>>>> "LD" == Laurent Duperval <laurent.duperval_at_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



-- 
Uwe Zdun
Specification of Software Systems, University of Essen
Phone: +49 201 81 00 332, Fax: +49 201 81 00 398
zdun_at_xotcl.org, uwe.zdun_at_uni-essen.de