Instanz Attribut als Klassvariable

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
d_rose
User
Beiträge: 57
Registriert: Dienstag 30. Oktober 2018, 11:34

Hallo,
ist es möglich eine eigentlich als Instanzattribut gedachte Variable, in einer anderen Klasse als Klassenattribut zu setzen.
Folgendes Beispiel:
Eine Klasse Fahrzeug mit den Attributen Räderanzahl, Nutzlast, usw.
Eine Klasse Fahrzeug welche von Fahrzeug erbt.
Und anschließend ein Klasse Fahrrad, welche von PKW erbt aber immer genau 2 Räder hat.

Wenn ich das so lese, so denke ich das die Klasse Fahrrad die Räderanzahl als Klassenvariable haben muss.
Aber gleichzeitig erbt sie von PKW welche als Attribut auch eine Räderanzahl verlangt, was sich ineffizient erweist, da ich ja dann zwei Räderanzahlen hätte.
Gibt es irgendeine elegante Art und Weise das zu machen ?
Benutzeravatar
ThomasL
User
Beiträge: 1378
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Ich stelle den Gedanken, Fahrrad als eine Unterklasse von PKW zu betrachten, stark in Frage.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
Perlchamp
User
Beiträge: 178
Registriert: Samstag 15. April 2017, 17:58

@d_rose:
Eine Klasse Fahrzeug mit den Attributen Räderanzahl, Nutzlast, usw.
Eine Klasse Fahrzeug welche von Fahrzeug erbt.
Und anschließend ein Klasse Fahrrad, welche von PKW erbt aber immer genau 2 Räder hat
ein und diesselbe Klasse (Fahrzeug), die voneinander erbt? ich bin Anfänger, weiß auch nicht, ob das geht, aber dies klingt beim Lesen bereits abenteuerlich.
Meist entstehen Programme (und daraus Klassen, etc.) aus dem Bezug (oder in Anlehnung) zur Wirklichkeit. Aber Fahhrad als Unterklasse von Farhrzeug (im Sinne von PKW) zu definieren empfinde ich bereits als unrealistisch.
Irgendwas ist immer !
wer lesen kann ist klar im Vorteil ;-)
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

d_rose hat geschrieben: Sonntag 24. Februar 2019, 18:20 Hallo,
ist es möglich eine eigentlich als Instanzattribut gedachte Variable, in einer anderen Klasse als Klassenattribut zu setzen.
Ein Klassenattribut ist für alle Instanzen dieser Klasse gleich, wird also geteilt, während Instanzattribute nur für die jeweiligen Instanzen gelten, also verschieden sein können.
d_rose hat geschrieben: Sonntag 24. Februar 2019, 18:20 Folgendes Beispiel:
Eine Klasse Fahrzeug mit den Attributen Räderanzahl, Nutzlast, usw.
Eine Klasse Fahrzeug welche von Fahrzeug erbt.
Und anschließend ein Klasse Fahrrad, welche von PKW erbt aber immer genau 2 Räder hat.

Wenn ich das so lese, so denke ich das die Klasse Fahrrad die Räderanzahl als Klassenvariable haben muss.
Aber gleichzeitig erbt sie von PKW welche als Attribut auch eine Räderanzahl verlangt, was sich ineffizient erweist, da ich ja dann zwei Räderanzahlen hätte.
Gibt es irgendeine elegante Art und Weise das zu machen ?
Alle Eigenschaften, also Attribute die du beschreibst sind Instanzattribute, da die Anzahl der Räder von der Art der Kindklasse abhängig sind. Wenn Fahrrad ein Kind von Fahrzeug ist, dann hat Fahrrad die Eigenschaften / Attribute von Fahrzeug (z.B. Bremsen, Räder, usw.), nur dass für diese Instanz eben die Anzahl der Räder unterschiedlich ist. Für PKW gilt dann eben etwas anderes.

Klassenattribute sind hier IMHO nicht sinnvoll, da keine der Eigenschaften fix ist, und für alle erbenden Klassen gleich.
When we say computer, we mean the electronic computer.
Benutzeravatar
__blackjack__
User
Beiträge: 14040
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ein Klassenattribut könnte hier ins Spiel kommen wenn die Anzahl der Räder grundsätzlich vom Typ abhängt, also wenn alle PKW vier Räder haben und alle Fahräder zwei Räder haben und beide von Fahrzeug abgeleitet sind, könnte man die Anzahl der Räder als Klassenattribut modellieren.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

@__blackjack__:

Meinst du das so in der Art?

Code: Alles auswählen

>>> class Fahrzeug:
...     pass
... 
>>> class PKW(Fahrzeug):
...     RAEDER = 4
... 
>>> class Fahrrad(Fahrzeug):
...     RAEDER = 2
... 
>>> 
>>> 
>>> pkw = PKW()
>>> fahrrad = Fahrrad()
>>> pkw.RAEDER
4
>>> fahrrad.RAEDER
2
Andere Variante, weil man ja sagen könnte dass Fahrzeug auch irgendwie RAEDER als Klassenattribut haben muss / kann / soll.

Code: Alles auswählen

class Fahrzeug:
    RAEDER = 4

class PKW(Fahrzeug):
    pass

class Fahrrad(Fahrzeug):
    RAEDER = 2
When we say computer, we mean the electronic computer.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Fahrzeug 4 Räder hat ist nicht sinnvoll. Dann ist es besser den Wert auf None oder ggf 0 zu setzten.
Sirius3
User
Beiträge: 18269
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: dass Fahrzeuge prinzipiell 0 Räder haben, bezweifle ich dann doch.

Fahrzeug sieht für mich wie eine abstrakte Klasse aus, die halt noch nicht vollständig ist, wenn es keine RAEDER gibt, wobei ANZAHL_RAEDER der bessere Name wäre.
Benutzeravatar
__blackjack__
User
Beiträge: 14040
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich würde Fahrzeug in dem Fall ``ANZAHL_RAEDER = None`` verpassen, weil die Klasse ja als Basis für die Dokumentation von gemeinsamen Eigenschaften und Verhalten dient und man dort dann etwas hat wo man die Dokumentation dran heften kann. (Ich benutze Sphinx und damit kann man auch direkt die Attribute dokumentieren und muss das nicht mit in den DocString der Klasse schreiben.) Oder einen konkreten Wert wenn ich erwarte, dass die meisten abgeleiteten Klassen den sowieso setzen werden und das nur in Ausnahmefällen anders belegt wird.

Also eigentlich ganz korrekt ja:

Code: Alles auswählen

class Fahrzeug(ABC):
    """"Abstrakte Fahrzeug Basisklasse."""
    
    #: Anzahl der Räder.
    ANZAHL_RAEDER: ClassVar[Optional[int]] = None
🤡
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich benutze auch meistens None wenn die Basisklasse keinen sinnvollen Wert annehmen kann. Ggf. ein object()-Sentinel. Aber die Delkaration von dem Typ zeigt eine Schwaeche auf - er ist ja eben genau *nicht* optional...
Benutzeravatar
__blackjack__
User
Beiträge: 14040
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Na gut, dann nur:

Code: Alles auswählen

class Fahrzeug(ABC):
    """"Abstrakte Fahrzeug Basisklasse."""
    
    #: Anzahl der Räder.
    ANZAHL_RAEDER: ClassVar[int]
Wobei das `Optional` ja nicht bedeutet das man es weglassen kann, sondern nur das es auch `None` sein darf. Und mit Typannotationen erzwingen das es auf einen Wert gesetzt wird, kann man AFAIK nicht.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Genau das wollte ich damit auch beleuchten - das ist eben eine Schwaeche des Typsystems. Java kennt ja nicht umsonst ein eigenes Schluesselwort dafuer. Und mE ist die Gefahr, durch einen Typen zu kommunizieren "hier kannst du auch optional sein" fataler, als es gar nicht zu tun.

Die Loesung bestaende natuerlich im Zweifel darin, eine abstrakte Methode einuzfuehren, und die Konstante damit zu ersetzen. Was ein bisschen traurig macht...
Benutzeravatar
__blackjack__
User
Beiträge: 14040
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@__deets__: Wie würde man das denn in Java machen? Also in der abstrakten Basisklasse ein statisches Feld vorgeben ohne dort einen Wert anzugeben und damit zu erzwingen das abgeleitete Klassen da etwas konkretes angeben müssen? Ich würde in Java auch über eine abstrakte Methode gehen, wobei das in Java weniger schmerzt weil man da ja sowieso triviale Getter Implementiert und gewohnt ist. Beziehungsweise könnte man da ja einen konkreten Getter implementieren und das statische Feld mit einem ungültigen Wert belegen auf den der Getter prüft. Ist dann natürlich erst eine Prüfung zur Laufzeit.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Klassenvariablen kann man in Java dafuer eh nicht nehmen. Das *muss* eine abstrakte Methode sein, weil Java ja auch keinen dynamischen Dispatch per Klasse fuer Klassenattribute/statische Variablen erlaubt, wie bei Python. Nur Methoden koennen das.

Ich kenne die Python-Typ-Annotationen und damit verbundenen Checker nicht gut genug, aber theoretisch zumindest sollte das ueberladen einer Property die dann per Deskriptor zur class-property wird auch moeglich sein. Aber da wird's langsam rostig, weil solche Sperenzchen eigentlich schon lange nicht mehr zum meinem Arsenal gehoeren - weniger meta ist mehr dieser Tage...
Benutzeravatar
__blackjack__
User
Beiträge: 14040
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Jo, früher war mehr Lameta… 🤡
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
Perlchamp
User
Beiträge: 178
Registriert: Samstag 15. April 2017, 17:58

@ d_rose:
mir stellt sich immer noch die Frage, warum Fahrrad von PKW erben *muss* (oder umgekehrt), also was diese beiden Klassen miteinander verbindet. Ein Fahrrad und ein PKW haben doch in der Realität auch kaum Gemeinsamkeiten, was willst du da vererben ?
Es gibt doch mit Sicherheit auch eine andere Möglichkeit, dies zu lösen. Welche Gemeinsamkeiten haben denn die beiden Klassen in deinem Script? Gibt's da überhaupt welche (wenn es bereits bei den Räder/Reifen hapert)?
Irgendwas ist immer !
wer lesen kann ist klar im Vorteil ;-)
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
Antworten