[ruby-de] Klasse redefinieren?

Jörg W Mittag ruby-de at joergwmittag.de
Fr Jun 23 02:47:13 JST 2017


Hallo,

>> Klassen haben keine Namen in Ruby, zumindest nicht in dem Sinne
>> wie z.B. in Java oder C♯.
> Nun ja, es gibt eine Konstant, die "Namensgeber" ist und einen Namen,
> der bleibt, selbst, wenn man die Konstante auf etwas anderes zeigen
> lässt:
>
> $ ruby -e 'class X; end;c=X;p X;X=nil;p c, c.name'
> X
> -e:1: warning: already initialized constant X
> -e:1: warning: previous definition of X was here
> X
> "X"
>
> Du siehst, der Name bleibt erhalten.
>
> […]
>
>> Es gibt eine Methode `Module#name`, diese hat aber nichts mit
>> einem Klassennamen im Sinne von Java oder C♯ zu tun.
> Warum nicht? In Java ist die Situation doch sehr ähnlich: es gibt
> einen Bezeichner für den Klassennamen im Quelltext und den kann man
> zur Laufzeit mit getName() und getSimpleName() abfragen.

Ich meinte hiermit den Begriff „Name“ wie er in der
Programmiersprachentheorie oder Übersetzertheorie verwendet wird,
in demselben Sinne, wie er auch in den zusammengesetzten Worten
wie „Namensraum“, „Namensauflösung“ oder „Namenskonflikt“
auftaucht, also als Möglichkeit, ein „Ding“ (Objekt, was auch
immer) im Quelltext eindeutig zu benennen und damit auch Zugriff
auf es zu erhalten. „Namen“ in *diesem* Sinne haben in Ruby nur
Methoden und Variablen (inkl. lokale Variablen, Parameter,
Instanzvariablen, Klassenvariablen, globale Variablen, Konstanten
und die diversen Pseudovariablen `self`, `nil`, `true`, …). Weder
Objekte im allgemeinen noch Module und Klassen im speziellen haben
diese Art von Namen.

In Java (und auch Smalltalk, z.B.) ist der Name einer Klasse eine
statische Referenz auf diese Klasse. Das ist in Ruby nicht der
Fall.

In *dem* Sinne meinte ich den Begriff „Name“ und in dem Sinne
habe ich auch die Verwendung des Begriffes durch den OP
verstanden. Bezöge er sich lediglich auf die `Module#name`-Methode,
wäre seine Frage trivial beantwortbar:

>Kann man einen Klassennamen wieder löschen?

```ruby
class Foo; end
def Foo.name; end

Foo.name #=> nil
```

Et voilà! Klassenname gelöscht.

Egal wie, die Frage ergibt keinen Sinn: in deiner Interpretation
ist sie trivial beantwortbar (und hat nichts mit dem Ändern der
Klassenhierarchie zur Laufzeit zu tun), in meiner Interpretation
ergibt sie keinen Sinn, da Klassen in Ruby keinen Namen in dem
Sinne haben.

Das kann nur der OP klären; auf diese Klärung warte ich aber
leider seit knapp anderthalb Wochen vergeblich.

>>> Problem:
>>> class R; end
>>> class S; end
>>>
>>> class A < R; end
>>> # A=nil
>>> class A < S; end    # error! ## wie erreicht man das?
>> Es ist auch unklar, was du mit „das“ meinst.
> Ich finde, es ist ganz deutlich: es geht darum, die
> Vererbungshierarchie zu ändern.

Für mich sieht es eher so aus, als versuche er, eine neue Klasse
zu erstellen, welche derselben Konstante zugewiesen ist wie die
vorherige. Klar, das erzeugen einer neuen Klasse ändert in
gewissem Sinne *immer* die Vererbungshierarchie, schließlich ist
hinterher eine Klasse mehr da als vorher, was offensichtlich eine
Veränderung darstellt. Ich interpretiere „Klassenhierarchie zur
Laufzeit ändern“ aber nicht so, dass damit das Hinzufügen neuer
Blattknoten gemeint ist sondern des Modifizieren eines Pfades
durch den Vererbungsbaum.

Andernfalls wäre die Antwort wiederum trivial:

```ruby
class Bar; end
```

Et voilà! Ich habe die „Klassenhierarchie zur Laufzeit geändert“:
`Object` hat eine neue Unterklasse, die es vorher nicht hatte,
ergo habe ich die „Klassenhierarchie geändert“ und „zur Laufzeit“
ist ohnehin trivial, da in Ruby praktisch alles zur Laufzeit
geschieht. (Ausnahmen wie das Deklarieren lokaler Variablen
bestätigen die Regel.)

>> Das hat aber nichts damit zu tun, die Klassenhierarchie zur
>> Laufzeit zu ändern.
> Doch, genau das versucht er doch.

Eben genau das ist mir unklar.

Die Betreffzeile lautet: „Klasse redefinieren?“ Das ist in Ruby
trivial möglich, denn dank offener Klassen ist *jede*
Klassendefinition eine potenzielle Redefinition.

Dies hat jedoch nicht zwingend etwas mit dem Ändern der
Klassenhierarchie zur Laufzeit zu tun.

Die Einleitung lautet: „Kann man einen Klassennamen wieder
löschen?“ Wie oben gezeigt, ist diese Frage je nach Interpretation
entweder unsinnig oder trivial.

Dies hat jedoch nicht im Entferntesten etwas mit dem Ändern der
Klassenhierarchie zur Laufzeit zu tun.

Das Quelltextschnipsel zeigt für mich den Versuch, eine neue
Klasse einer Konstanten zuzuweisen, welcher bereits vorher eine
Klasse zugewiesen war. Der einzige Hinweis darauf, was dieser
Quelltext bewirken soll lautet: „# error! ## wie erreicht man das?“
Ich habe gezeigt, dass man den Fehler beheben kann, indem man an
der Stelle, wo das auskommentierte `A = nil` steht, statt dessen
`remove_const :A` schreibt.

Auch dies hat nichts mit dem Ändern der Klassenhierarchie zur
Laufzeit zu tun.

Dieser Begriff taucht erst ganz am Ende auf, jedoch ohne eine
Erklärung, wie er mit dem Rest der Frage zusammenhängt.

Es fehlt schlicht und ergreifend ein Erfolgskriterium anhand
dessen es möglich wäre, herauszufinden, ob die Frage zufrieden
stellend beantwortet ist oder nicht. Die Frage enthält einen
Schnipsel Quelltext mit einem Fehler. Ich habe aufgezeigt, wie
man diesen Fehler behebt.

Der OP hat aber keinerlei Anzeichen gegeben, ob dies sein Problem
löst oder nicht, und die Frage selbst enthält keinerlei
nachvollziehbare Kriterien (zum Beispiel eine Spezifikation oder
Testfälle). Daher kann nur der OP sagen, ob meine Lösung korrekt
ist oder nicht.

Beste Grüße,
    Jörg.


Mehr Informationen über die Mailingliste ruby-de