Abstract base classes with TclOO

Introduction

Actually, the concept of abstract base classes is unheard of in TclOO, unlike in C++ and in Java. In C++, a class becomes abstract as soon as there is a pure virtual function in the class. This means that the function has no body, but is declared with = 0. A pure virtual function cannot be called, thus the class cannot be used to create objects. As soon as a new class deriving from it implements all pure virtual functions by overriding them, the derived class can be used to create objects.

In Java, classes can be directly declared as being abstract by using the word abstract. Additionally, at least one method is also declared abstract and has no body. The result is the same as in C++.

A case for this might be that there is an abstract base class account, but every existing account must be created using some kind of derived class like checking account, savings account, trading account and so on. If someone tries to create an object using the class account, an error is thrown. In C++, this error will be thrown while compiling, but due to the dynamic nature of Tcl it would be thrown at runtime, since there is no compiling process.

The TclOO way

In TclOO, there is neither abstract nor virtual, and a method cannot be declared without a body. The only part of a class which is being used when creating a new object, is the constructor. So the constructor has to check whether it is being chain called from the constructor of a derived class or directly. In case of being used to create an object of the class itself, an error must be thrown.

oo::class create myAbstractClass {
  constructor {} {
    if {![lindex [self call] 1]} {
      return -code error "class '[info object class [self]]' is abstract"
    } ;# if
    puts "constructor of myAbstractClass"
  } ;# constructor
}

oo::class create myDerivedClass {
  superclass myAbstractClass
  
  constructor {} {
    puts "constructor of myDerivedClass"
    next
  }
}


set o1 [myDerivedClass new]
puts $o1
set o2 [myAbstractClass new]
puts $o2

The test shows that the first object o1 can be created, but the attempt to create an object of class myAbstractClass fails with an error message.