Aus Linux-Magazin 07/2001

Objektorientierung mit Tcl

Tcl ist das bestgehütete Geheimnis der IT-Industrie – und sehr lebendig. Die im Auftakt unserer Tcl-Reihe "Feder-Lesen" vorgestellte objektorientierte Erweiterung mit dem sperrigen Namen [incr Tcl] hat einen guten Teil zur Verbreitung von Tcl beigetragen.

Mit “Feder-Lesen” startet das Linux-Magazin eine Reihe, die in loser Folge über Neuigkeiten aus der Tcl-Welt berichtet. Dabei werden jeweils Werkzeuge oder Erweiterungen vorgestellt, mit deren Hilfe sich Aufgaben in Tcl besonders leicht und elegant lösen lassen. Da sich in der letzten Zeit das Entwicklungsmodell von Tcl geändert hat, beginnt die erste Folge mit den Änderungen und Neuerungen. Im Anschluss wird die objektorientierte Erweiterung [incr Tcl] vorgestellt.

Schon seit Jahren trägt die Skriptsprache Tcl den Stempel “The IT-Industry’s best kept secret”. Obwohl die Gemeinde der Tcl-Programmierer weiter zunimmt, ist diese selbstironische Bezeichnung durchaus berechtigt. Während an jeder Ecke über Lösungen mit den Konkurrentinnen Perl oder Python geredet wird, verrichtet Tcl seinen Dienst ohne viel Aufhebens im Verborgenen.

Das hat seinen Gründe: So gibt es bis heute immer noch kein Äquivalent zum Perl-CPAN oder zu Python.org, die Suche nach Tcl-Erweiterungen oder nach Dokumentation für ein bestimmtes Problem kann sich daher schwierig gestalten. Der Kasten “Tcl: Was bisher geschah” beleuchtet deshalb den Stand der Dinge, wie es dazu kam und was die nahe Zukunft bringen wird.

Durch viele Änderungen in den letzten Monaten sind viele Erweiterungen und Informationen inzwischen noch schwerer zu finden, als sie das vorher schon waren. Die Informationsseite der Entwickler liegt nun bei Active State [1]. Sie enthält viele Verweise auf Dokumentation, Erweiterungen und Programme. Eine weitere Möglichkeit ist die Tcl-Foundry bei Sourceforge [2]. Bei vielen Problemen des Alltags bietet sich ein Blick ins Tcl’ers Wiki an [3]. Wer auch hier noch nicht fündig wird, für den ist die Newsgroup [4] die Ultima Ratio für alle Fragen zu Tcl.

Nicht nur in der Tcl-Newsgroup taucht immer wieder der alte Kritikpunkt an Tcl auf, nämlich die fehlende Objektorientierung. Glücklicherweise lässt sich diese Fähigkeit leicht durch eine Erweiterung nachrüsten – eine sehr ausgereifte und beliebte OO-Erweiterungen ist [incr Tcl], das Thema des Monats im Feder-Lesen.

Doppelplus gut: [incr Tcl]

Auch bei Skriptsprachen kommt häufig der Wunsch nach den Segnungen der objektorientierten Entwicklung auf: Klassen, Vererbung, Datenkapselung und mehr. Obwohl sich Tk schon sehr objektorientiert anfühlt, unterstützt Tcl außer den Namensräumen keine OO-Features. Hier springt die Erweiterung [incr Tcl] in die Bresche. Nicht nur der Name ähnelt dem von C++: Das Tcl-Kommando incr ist das Äquivalent zu dem Postfix ++ bei C, [incr Tcl] möchte ebenso wie C++ eine Erweiterung der Grundsprache um OO-Features sein. Die Erweiterung ist bei Sourceforge zu finden [5], sie ist aber auch in den meisten Linux-Distributionen enthalten.

Vor ihrer Verwendung muss die Erweiterung in eine tclsh oder wish geladen werden, das geschieht mit dem Kommando package require Itcl. Alle Kommandos von [incr Tcl] sind im Namensraum itcl definiert, entweder verwendet man sie mit vollem Namen oder importiert sie in den aktuellen Namensraum. Im Folgenden geht es am Beispiel eines Editors für Type-1-Schriften um die Programmierung mit dieser Erweiterung.

Klassenweise

Klassen sind der Grundbaustein der objektorientierten Programmierung, eine gewisse Vertrautheit mit dem Klassenkonzept wird hier vorausgesetzt. Bevor Objekte erzeugt und verwendet werden können, ist eine Klasse zu definieren. Die Klasseneinteilung legt fest, welche Variablen und Methoden existieren und welche Aufgaben sie erfüllen. Um Klassenvariablen zu definieren, reicht die Aufzählung der Namen mit dem Kommando variable.

Methoden werden ähnlich wie normale Tcl-Prozeduren definiert: Nach dem Namen folgen die Eingabeparameter und danach ein Block mit dem eigentlichen Quellcode. Innerhalb dieses Blocks kann direkt auf die Klassenvariablen zugegriffen werden. Außerdem existiert dort die Variable this, die eine Referenz auf das aktuelle Objekt enthält. Zusätzlich lassen sich zwei besondere Methoden definieren: der Konstruktor und der Destruktor. Sie werden beim Erzeugen beziehungsweise beim Löschen eines Objekts aufgerufen. Der Aufbau der beiden ähnelt wieder normalen Prozeduren, nur hat der Destruktor keine Eingabevariablen.

Als Beispiel dient im Listing 1 die Definition einer Punkt-Klasse. Jeder Punkt hat eine x- und eine y-Koordinate, die durch den Konstruktor gesetzt werden. Außerdem lässt sich ein Punktobjekt verschieben.

Die mit [incr Tcl] definierten Klassen sind so ähnlich wie die Tk-Widgets verwendbar. Wie Listing 2 zeigt, lautet der Aufruf zum Erzeugen eines neuen Objekts Klassenname Objektname ?Parameter?. Der Objektname lässt sich entweder explizit wählen oder mit #auto automatisch vergeben. Das Objekt steht nun unter diesem Namen als neues Kommando zur Verfügung, die Syntax ist Objektname Methode ?Argumente?. Bei jedem Objekt stehen die Methoden cget, configure und isa zur Verfügung.

Mit den ersten beiden lassen sich die als public definierten Variablen abfragen und setzen. Die Methode isa überprüft, ob ein Objekt Mitglied einer bestimmten Klasse ist. Dazu kommen noch die selbst definierten Methoden, hier die Methode verschieben. Die Kommandos delete object Objektname und delete class Klassenname löschen das Objekt oder die Klassen wieder.

Verwandtschaft

Die Umrisse von Type-1-Schriften bestehen aus Geraden und Kurven. Jede Gerade wird durch zwei Knotenpunkte definiert, die Kurve durch zwei Knotenpunkte und zwei Kontrollpunkte. Um zwischen den beiden verschiedenen Punktarten unterscheiden zu können, wird jede als eigene Klasse eingeführt.

Bei dem in Listing 3 beschriebenen Beispiel erben die beiden Klassen von der Klasse Punkt. Hierzu dient das Schlüsselwort inherit. Der Konstruktor reicht die notwendigen Variablen an die Basisklasse durch. In der Definition der abgeleiteten Klasse lassen sich weitere Variablen und Methoden hinzufügen – wie im Listing 3 die Methode koordinaten in der Klasse Knotenpunkt.

Bislang fehlt eine Möglichkeit, die Objekte im Canvas darzustellen. Normalerweise würde man diese Methode in der Punkt-Klasse unterbringen. Um allerdings die Mehrfachvererbung zu demonstrieren, definiert das Beispiel extra eine eigene Klasse Zeichnen.

Wie der Kontrollpunkt zeigt, ist auch die Mehrfachvererbung ziemlich einfach zu verwenden. Allerdings ist sie nicht ganz unproblematisch. Man stelle sich nur die Frage: Was passiert, wenn zwei Basisklassen jeweils eine Methode mit dem gleichen Namen enthalten. Bei [incr Tcl] wird die Methode aus der zuerst geerbten Basisklasse verwendet, was eventuell gar nicht gewollt ist. Ein weiteres Problem, das bei Mehrfachvererbung entstehen kann, ist die Diamond Inheritance (siehe Abbildung 1). Dieser Fall wird bei [incr Tcl] gar nicht unterstützt.

Eine Type-1-Schrift besteht aber nicht nur aus einzelnen Punkten, es fehlen noch die Umrisse. Damit lässt sich ein weiteres Feature der objektorientierten Programmierung einführen: die Delegation.

Damit ist gemeint, dass eine Klasse Aufgaben an Objekte einer anderen Klasse vergibt. In diesem Fall wird eine Gerade durch zwei Knotenpunkte definiert und muss sich um die Darstellung und Datenhaltung nicht selber kümmern. Immer wenn die Linie ihre Knotenkoordinaten benötigt, kann sie diese von den Knotenobjekten abfragen. Die Knoten werden dazu in der Linien-Klasse gespeichert (Listing 4).

Meins!

Abbildung 1: Mögliche und unmögliche Beziehungen zwischen Klassen bei [incr Tcl]. Vererbung, Mehrfachvererbung und Delegation sind erlaubt, nicht aber die Diamond Inheritance.

Abbildung 1: Mögliche und unmögliche Beziehungen zwischen Klassen bei [incr Tcl]. Vererbung, Mehrfachvererbung und Delegation sind erlaubt, nicht aber die Diamond Inheritance.

Zur Datenkapselung gehört auch, dass eine Klasse entscheiden kann, wer auf ihre Variablen und Methoden zugreifen darf. [incr Tcl] unterstützt drei verschiedene Stufen:

n public: Die Methode oder Variable ist für alle zugänglich.

n protected: Nur innerhalb der Klasse selbst oder in von ihr abgeleiteten Klassen verwendbar.

n private: Nur innerhalb der Klasse selbst zugänglich.

Die Koordinaten eines Punkts waren bisher durch configure beliebig modifizierbar, ohne dass etwa eine Überprüfung der Werte stattgefunden hätte. Sind die Koordinaten als protected definiert, sind sie nur noch mit der Methode verschieben änderbar.

class Punkt {
  protected variable x
  protected variable y
  # ...
}

Die abgeleiteten Klassen dürfen direkt auf die Variablen zugreifen, ohne auf die speziellen Methoden angewiesen zu sein. Würde man die Koordinaten dagegen in die Stufe private einordnen, könnten auch die abgeleiteten Klassen nicht mehr direkt auf sie zugreifen.

Alles in allem

Mit [incr Tcl] lassen sich auf einfache Weise Klassen inklusive Vererbung definieren, dabei können Variablen und Methoden in unterschiedlichen Stufen vor Zugriff geschützt werden. Die Möglichkeiten lehnen sich – inklusive der Mehrfachvererbung – an C++ an. Übrigens können [incr Tcl]-Klassen sogar von C++-Klassen erben. Ein besonders gutes Beispiel ist die CORBA-Erweiterung Combat von Frank Pilhofer [6].

Abbildung 2: Der Type-1-Editor baut auf den Programmstücken aus diesem Artikel auf.

Abbildung 2: Der Type-1-Editor baut auf den Programmstücken aus diesem Artikel auf.

Die Verwendung der Objekte ist jedem Anwender vertraut, der schon mal mit Tk gearbeitet hat. Die Möglichkeiten von [incr Tcl] sind damit ohne großen Lernaufwand nutzbar. Die zuerst in [incr Tcl] entwickelten Namensräume haben schon seit einigen Jahren den Weg in das normale Tcl gefunden, deshalb wurde auf sie hier nicht weiter eingegangen. Weiterführende Literatur zu [incr Tcl] findet sich auf [7].

Die vorgestellten Beispiele und ein daraus abgeleiteter Editor (Abbildung 2) sind auf [8] zu finden. Bislang fehlt allerdings jeglicher Quelltext, um die Buchstaben im Canvas darzustellen. Auf die Möglichkeiten des Canvas-Widgets wird dann das nächste Feder-Lesen eingehen. (fjl)

Listing 1: Klassendefinition mit Methoden und Variablen

package require Itcl
namespace import itcl::*

class Punkt {
 public variable x
 public variable y
 
 constructor {_x _y} {
   set x $_x
   set y $_y
   
   puts "Konstruktor: $this, $x:$y"
 }
 
 destructor {}
 
 public method verschieben {dx dy} {
   set x [expr {$x + $dx}]
   set y [expr {$y + $dy}]
   return [list $x $y]
 }
}

Listing 2: Die interaktive Punkt-Klasse

% Punkt p1 10 10
p1
% p1 cget -x
10
% p1 configure -x 200
% p1 cget -x
200
% Punkt #auto 20 20
punkt0
% punkt0 verschieben 10 20
20 30
% punkt0 isa Punkt
1
% punkt0 isa Oink
0
% delete object p1 punkt0
% delete class Punkt

Listing 3: Vererbung und Mehrfachvererbung

class Zeichnen {
 constructor {} {}
 destructor {}
 
 public method zeichnen {} {
   if {[$this isa Kontrollpunkt]} {
      # zeichne Kontrollpunkt
   } elseif ...
 }
}

class Knotenpunkt {
 inherit Punkt

 constructor {_x _y} {
   Punkt::constructor $_x $_y
 } {
   # Konstruktor des Knotenpunkts
 }
 
 public method koordinaten {} {
   return [list $x $y]
 }
}

class Kontrollpunkt {
 inherit Punkt Zeichnen
 
 constructor {_x _y} {
   Punkt::constructor $_x $_y
   Zeichnen::constructor
 } {
   # Konstruktor des Kontrollpunkts
 }
}

Listing 4: Delegation

class Linie {
  private variable k1
  private variable k2
  
  constructor {_k1 _k2} {
    foreach k {$_k1 $_k2} {
      if {![$k isa Knotenpunkt]} { 
        error "Knoten $k ist kein Knotenpunkt!"
      }
    }
    set k1 $_k1
    set k2 $_k2
  }
}

Tcl: Was bisher geschah

John Ousterhout, der Vater von Tcl. Mit "Tcl/Tk for Dummies" hat er aber offenbar noch Probleme.

John Ousterhout, der Vater von Tcl. Mit “Tcl/Tk for Dummies” hat er aber offenbar noch Probleme.

John Ousterhout, der geistige Vater der Sprache, war auch viele Jahre ihr Hauptentwickler. Er entwarf die Grundlagen als Professor an der Universität von Berkeley, bevor er mit einem Entwicklerteam zu Sun Microsystems wechselte. Dort schuf das Team den Bytecode-Compiler und machte erste Schritte in Richtung Unicode. Bevor mit Tcl 8.1 die Internationalisierung vollendet war, verließ Ousterhout jedoch Sun, um die eigene Firma Scriptics ins Leben zu rufen.

Scriptics hatte das Ziel, Entwicklungswerkzeuge (Tcl Pro) und professionellen Support für Tcl zu verkaufen. Damit sollte auch die Weiterentwicklung der Sprache finanziert werden. Unter der Ägide von Scriptics wurden die Releases 8.1 bis 8.3 entwickelt. Allerdings war der Verkauf von Tcl Pro wohl nicht ausreichend, um damit die hauptberuflichen Tcl-Entwickler zu finanzieren.

Das ist ein klassisches Dilemma von Firmen im Open-Source-Umfeld, ein ähnliches Problem stellte sich vor kurzem bei Python. Scriptics wurde deshalb in Ajuba Solutions umbenannt. Neuer Schwerpunkt war der Verkauf von B2B-Produkten (Business-to-Business), mit denen sich Datenbanken per XML ins Internet integrieren lassen. In der Folge kannten sich die Entwickler bei Ajuba wohl zu gut mit XML aus – die ganze Firma wurde schließlich von Interwoven übernommen, einem großen Hersteller von B2B-Software, der allerdings an der Weiterentwicklung von Tcl kein Interesse hat.

Wie stellt sich die Situation für Tcl etwa ein halbes Jahr später dar? Schon zu Ajubas Zeiten hatte Ousterhout den Stammsitz der Tcl-Quellen zu Sourceforge verlagert. Dort finden sich übrigens neben dem Interpreter etwa 200 weitere Projekte, die Tcl-Werkzeuge oder Erweiterungen entwickeln. Hierzu gehören auch die Werkzeuge der Tcl-Pro-Suite. Da Interwoven die Kronjuwelen von Scriptics nicht vermarkten wollte, wurden sie noblerweise als Open Source veröffentlicht.

Die Lagerung der Quellen ist die eine, auf der anderen Seite galt es, die Leitung aus den Händen eines wohlwollenden Diktators in die der Entwicklergemeinde zu geben. Die Lösung ist das Tcl Core Team (TCT). Die Tcl-Nutzer hatten im Internet bestimmt, wer Mitglied im TCT ist und damit über die Richtung der Weiterentwicklung bestimmt. Vorschläge für Entwicklungen (meist inklusive der Lösung) werden als Tcl Improvement Proposal (TIP) eingereicht. Nach einer Diskussion in der öffentlichen Mailingliste stimmen die TCT-Mitglieder darüber ab.

Mit diesem Verfahren hat die Weiterentwicklung inzwischen ein beachtliches Tempo aufgenommen. Dennoch hätte der Wegfall der von Scriptics bezahlten hauptamtlichen Tcl-Entwickler natürlich eine große Lücke hinterlassen. Doch hier sprang die Firma Active State ein. Sie ist schon bei Perl- und Python-Anwendern für Support und Portierungen bekannt, mit Tcl hat sie nun alle drei großen Skriptsprachen im Angebot. Mit Jeffrey Hobbs und Andreas Kupries sind inzwischen zwei prominente Tcl-Entwickler bei Active State gelandet.

Von Active State wird es in absehbarer Zeit auch die Batteries-included-Distribution geben, mit der das ewige Suchen nach der passenden Erweiterung ein Ende haben soll. Zur Zeit wird gerade an der Tcl-Version 8.4 gearbeitet, eine neue Alpha-Release sollte schon bei Drucklegung dieses Heftes auf Sourceforge bereitstehen. Sowohl in der Mailingliste des TCT wie auch in der Newsgruppe Comp.lang.tcl ist jedoch schon ein erstes Donnergrollen für Tcl 9.0 zu vernehmen. Man kann noch einiges erwarten.

Infos

[1] Informationsseite für Entwickler: http://tcl.activestate.com

[2] Tcl-Foundry bei Sourceforge: http://sourceforge.net/foundry/tcl-foundry

[3] Tcl’ers Wiki: http://mini.net/cgi-bin/wikit/0.html

[4] Tcl-Newsgruppe: news://comp.lang.tcl

[5] [incr Tcl] bei Sourceforge: http://sourceforge.net/projects/incrtcl/

[6] Combat, eine Tcl-CORBA-Erweiterung: http://www.fpx.de/Combat/

[7] Die Tcl-Tk-Homepage: http://www.tcltk.org/

[8] Der Type-1-Editor: http://www.tu-harburg.de/~skfcz/tcltk.html

Der Autor

Carsten Zerbst ist wissenschaftlicher Mitarbeiter an der TU Hamburg-Harburg. Neben der Forschung über die Dienste-Integration an Bord von Schiffen beschäftigt er sich mit Tcl in allen Lebenslagen.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben