Laden...

alle objekte einer Klasse auswerten

Erstellt von key-board vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.372 Views
K
key-board Themenstarter:in
33 Beiträge seit 2013
vor 9 Jahren
alle objekte einer Klasse auswerten

Hallo
Ich suche schon eine ganze weile aber finde nichts passendes.

Es geht darum, ich habe ein paar verzweigte Klassen nach dem Schema


class Haus
{
  class Aufgang
  {
    public void set_Zimmer(int x)
    {...}
    public int get_Zimmer()
    {...}
    int Zimmer
    public void set_BettenJeZimmer(int y)
   {...}
    public int get_BettenJeZimmer()
    {...}
    int BettenJeZimmer
  }
  public int BettenImHaus()
  {
  Nehme aus jedem Aufgang des Hauses die Anzehl der Zimmer und BettenJeZimmer und errechne die Betten im Haus  
return BettenImHaus;
  }
}

verwenden will ich die so


Haus Sonnenschein = new Haus();
Sonnenschein.Aufgang Sonnenblume = new Sonnenschein.Aufgang();
Sonnenschein.Aufgang Primel = new Sonnenschein.Aufgang();

Sonnenschein.Sonnenblume.set_Zimmer(20);
Sonnenschein.Sonnenblume.set_BettenJeZimmer(5);
...
int Plätze = Sonnenschein.BettenImHaus();

zumindest stell ich mir das so vor.
Mein Problem daran ist
a) der zuletzt gebrachte codeschnipsel funktioniert nicht
der sagt dann
"...Form1.Sonnenblume" ist ein(e) "Feld" wird aber wie ein(e) "Typ" verwendet.
Ich finde nicht wie ich ein Objekt der "Aufgang" klasse in der "Haus" klasse erstellen kann. Geht das Überhaupt?

b) gibt es eine möglichkeit die sache mit Sonnenschein.BettenImHaus() umzusetzen mit egal wie vielen erstellten Aufgängen? oder muss dann alles einzeln und von Hand Programmiert werden?.

Hoffe ich hab mein Problem Kreativ und verständlich rübergebracht.
Hab mich an einer alten Jugendherberge in der ich früher mal war inspirieren lassen.
Danke schonmal.

Bitte nicht solche antworten wie Steht im msdn... Hab da schon geschaut und gelesen aber nix gefunden 😕 Ich weiß dass ich höchst wahrscheinlich nicht richtig geschaut habe oder Tomaten auf den Augen habe. wenn dann bitte mit Verweis/Link wo ich nochmal lesen muss.
Danke

R
228 Beiträge seit 2013
vor 9 Jahren

Ich würde die Klassen nicht verschachteln sondern getrennt voneinander Programmieren und dann zwischen den Klassen eine Assoziation herstellen:


class Haus
{
  public  List<Aufgang> Sonnenaufgänge {get; set; }/* Ich habe es so verstanden, dass du   mehrere Speichern möchtest, deswegen eine List<T> */


  public Haus(){
    Sonnenaufgänge  = new List<Aufgang>();
   }
 
 
  public int BettenImHaus()
  {
     foreach(var aufgang in Sonnenaufgänge ){
       //BettenImHaus += aufgang.Zimmer verarbeiten usw.
     }
     return BettenImHaus;
  }

} 

class Aufgang
{
    public void set_Zimmer(int x)
    {...}
    public int get_Zimmer()
    {...}
    int Zimmer
    public void set_BettenJeZimmer(int y)
   {...}
    public int get_BettenJeZimmer()
    {...}
    int BettenJeZimmer
}







Haus haus = new Haus();
Aufgang auf = new Aufgang ();
auf.set_Zimmer(20);
auf.set_BettenJeZimmer(5);

haus.Sonnenaufgänge.add(auf);






2.078 Beiträge seit 2012
vor 9 Jahren

Rioma hat bereits die Liste als Hilfsmittel gezeigt, ich versuche aber mal, das Ganze anders zu beschreiben. Da ich mit deinem Aufgang-Beispiel nicht so ganz warm werde, verwende ich das Beispiel Betten im Haus.

Zuerst zum letzten Satz:
Es ist schwierig etwas zu finden, wenn man nicht weiß, wonach man suchen muss 😉
In deinem Fall suchst du vermutlich weniger nach einer bestimmten Technologie, sondern mehr nach Herangehensweisen, wie du eine Software auf baust. Da finde ich auch manchmal nicht das, was ich suche, bis ich dann durch Zufall über das Gesuchte stoße und fest stelle, dass ich an der ganz falschen Stelle gesucht habe. 😄 Es hilft aber, die Frage für ein Forum aufzuschreiben und dann nicht abzusenden 😉 Dabei zwingst du dich umzudenken und dich noch einmal intensiver mit der Frage an sich auseinander zu setzen, es wird auf einmal vieles klarer.

Nun zum Problem:
Du möchtest die Betten haben, die in einem Haus stehen.
Es gibt keinen Weg, die Objekte zu suchen, die diesen Typ haben. Vielleicht gibt es schmutzige Tricks, indem man den RAM absucht und analysiert, aber das ist Mist, selbst wenn das ohne größeren Aufwand gehen sollte.
Die bessere Herangehensweise ist die, dass das Haus von Anfang an weiß, wie viele Betten in ihm stehen, es wird dem Haus nämlich gesagt.

Stell dir das so vor:
Dem Bett ist das Haus, in dem es steht, ziemlich egal. Es kann sonst wo stehen und funktioniert immer. Ein Haus ist ohne ein Bett aber nicht mehr so toll, schließlich möchte man in einem Haus auch schlafen können und ohne Bett ist das ziemlich unbequem.
Anders ausgedrückt: Das Haus braucht das Bett, nicht umgekehrt.
Aus dem Grund gehört es auch zur Aufgabe des Hauses, sich darum zu kümmern, dass ein Bett da ist, bzw. die Betten zu verwalten.

Der Ablauf sieht dann ungefähr so aus:
Du erstellst ein Haus. Das ist leer, nichts drin und alles was es kann ist den Regen abhalten. Wenn du das nun einrichten willst, gehst du hin, besorgst die Möbel (damit auch dein Bett) und gibst sie dem Haus, damit sie in dem Haus stehen. Das Haus bekommt dann das Bett und merkt sich, dass es ein Bett hat - oder mehrere.

Im Code könnte das so aussehen:

public class Haus
{
    public ICollection<Bett> Betten { get; private set; }

    public Haus()
    {
        Betten = new List<Bett>();
    }
}

Und die Nutzung dann so:

var meinHaus = new Haus();
var meinNeuesBett = new Bett();
meinHaus.Betten.Add(meinNeuesBett);

var anzahlBetten = meinHaus.Betten.Count;
forech (var bett in meinHaus.Betten)
{
    // ...
}

Kurz zur Erklärung:

Ich habe das Interface ICollection verwendet. List und eine ganze Reihe anderer Klassen, die Auflistungen repräsentieren, implementiert dieses Interface.
ICollection beschreibt jede Auflistung, die du ändern kannst, also Elemente hinzufügen oder entfernen und genau das brauchst du hier ja. Du möchtest Betten hinzufügen oder entfernen können.
So sparst du dir eine Methode zum Hinzufügen der Betten.

Es könnte aber auch so gehen:

public class Haus
{
    private readonly IDictionary<Bett, Zimmer> _betten;
    public IEnumerable<Bett> Betten
    {
        get { return _betten; }
    }

    public Haus()
    {
        betten = new Dictionary<Bett, Zimmer>();;
    }

    public void AddBett(Bett bett, Zimmer zimmer)
    {
        _betten.Add(bett, zimmer);
    }
}

Hier verwende ich ein privates Dictionary, damit das Haus sich zu jedem Bett merken kann, wo es genau steht, in diesem Fall reicht, welches Zimmer.
Zum Auslesen der Betten nur IEnumerable (Jede Auflistung implementiert IEnumerable, auch ICollection), da beim Aufruf nicht möglich sein soll, Betten hinzuzufügen, ohne dass das Zimmer gemerkt werden kann, denn dafür gibt es die AddBett-Methode.

Im Endeffekt musst du gar nicht mehr "herausfinden", wie viele Objekte es von einem Typ gibt, oder wie viele Betten/Aufgänge es gibt, denn es ist bereits bekannt.
Das ist die übliche Herangehensweise, wenn ein Objekt Informationen benötigt. Es fragt nach diesen Informationen, entweder beim Aufruf einer Methode oder im Konstruktor. Oder es weigert sich seinen Dienst zu erfüllen (Exception), wenn vorher bestimmte Eigenschaften keinen bestimmten Wert haben.

Ein anderes Beispiel:
Stell dir einen Schürzenjäger vor und ein Freund fragt ihn, wie die Frauen denn hießen, mit denen er bereits zusammen war. Er wird bestimmt nicht jede Frau einzeln fragen, das würde eine ganze Weile dauern, jede lebende Frau zu fragen. Stattdessen merkt er sich die Namen auf einem Zettel in einer - wer hätte es gedacht 😉 - Liste. So kann er ganz einfach alle Namen ablesen.

Wie das Problem gelöst wird, hängt immer vom konkreten Fall ab. Es gibt wie immer mehrere Lösungsmöglichkeiten, daher hoffe ich, du verstehst ungefähr die Denkweise und wie du bei zukünftigen oder aktuellen Problemen selber diesen Gedankengang finden und die Software entsprechend aufbauen kannst. Wichtig ist dabei: Lass den Kram raus, den du nicht wirklich brauchst, es dürfte den Freund vom Schürzenjäger eher weniger interessieren, wo jede einzelne Frau gearbeitet hat.

Was deine Klassen angeht:
Verschachtelte Klassen sind (fast) immer eine schlechte Idee.
Ausnahmen bestätigen die Regel, ich habe selber vor Kurzem gehabt, aber in .NET fällt mir jetzt spontan Keine ein. Im Dictionary gibt es verschachtelte Klassen, aber ich vermute, das sind Altlasten von früher. Es kann aber auch sein, dass diese Nestes Classes ganz bestimmte Funktionen haben, die nur und wirklich nur für diese eine Klasse sinnvoll sind.

K
key-board Themenstarter:in
33 Beiträge seit 2013
vor 9 Jahren

Ah vielen Dank
Sorum geht das also auch. Supi. Kannte das mit der Liste noch nicht.
versteh ich das richtig, dass dieses List<Aufgang> mir die Möglichkeit gibt
ein Objekt der Klasse Aufgang zu erstellen also

Aufgang Sonnenblume = new Aufgang()

und mit dem Haus Sonnenschein eindeutig zu verknüpfen.
Sprich im schlimmsten fall auch haben kann
Haus Mondschein Aufgang Sonnenblume?
Dass das dann unglückliche benennung ist ist klar aber der rechner würde die beiden Sonnenblumenaufgänge nicht verwechseln?

und könnte ich auf die Liste so zugreifen nach dem schema (mit deiner benennung)?

haus.auf.set_Zimmer

Es geht ja im eigentlichen Projekt ja auch nicht um Häuser und Aufgänge. Hab das nur gewählt um es verständlicher zu machen.

Ich denke nämlich mal dass nicht jeder durchsieht wenn ich von Netzknoten Lasten und Transferleistungen rede.

Nur um Klartext zu reden will ich jede Last eindeutig einem Netzknoten zuweisen, und in einem Energieverteilungsnetz gibt es ja meinetwegen nicht nur ein Haus oder eine Windkraftanlage. Es wird entsprechend mehrere Netzknoten(Haus) geben und jeder hat halt auch mehrere Lasten(Aufgänge) und die dann ihre zur Berechnung relevanten Daten(Zimmer, BettenImZimmer,...)

PS @Palladin007 sorry hab deine Antwort erst gelesen als ich mit meiner hier fertig war^^ vielleicht kannst du meinem Klartext besser folgen als der aus der Luft gegriffenen Haus Aufgang Zimmer/Bett Geschichte

Anstatt der BettenImHaus Zählung sollte án der Stelle auch eher eine Machenstromanalyse stattfinden. Hatte eben nur befürchtet dass damit niemend etwas anfangen kann. Und um nicht durcheinander zu kommen hatte ich mir halt die herangehensweise mit den "geschachtelten Klassen" überlegt. Bei SPS Programmierung scheint das auch normal zu sein sowas zu machen. Zumindest bei dem letzten Projekt wo ich mitgearbeitet habe. Daher hab ich die Idee.

F
10.010 Beiträge seit 2004
vor 9 Jahren

Bei SPS Programmierung scheint das auch normal zu sein sowas zu machen

SPS Programmierung und OOP sind aber 2 ganz unterschiedliche paar Schuhe.

Schau dir mal die Grundlagen von OOP mit C# an, dann wird dir z.b. auffallen das deine ganzen set_/get_ Funktionen in C# eher Properties sind.
Auch wird dir dann sicherlich auffallen das du das Pferd von der falschen Seite aufzäumst.

K
key-board Themenstarter:in
33 Beiträge seit 2013
vor 9 Jahren

Bei SPS Programmierung scheint das auch normal zu sein sowas zu machen
SPS Programmierung und OOP sind aber 2 ganz unterschiedliche paar Schuhe.

Schau dir mal die Grundlagen von OOP mit C# an, dann wird dir z.b. auffallen das deine ganzen set_/get_ Funktionen in C# eher Properties sind.
Auch wird dir dann sicherlich auffallen das du das Pferd von der falschen Seite aufzäumst.

das stimmt SPS und OOP hat nicht viel gemein. Hatte mich davon ja nur inspirieren lassen. Und was OOP angeht behaupte ich zwar von mir ich kann das ansatzweise, zumindest konnte ich bisher alles lösen was ich gebraucht habe, aber in wirklichkeit weiß ich auch dass ich in OOP ein noob bin. Gebe auch ehrlich zu vieles nicht richtig verstanden zu haben, aber deshalb mach ich immer weiter und versuche stendig dazu zu lernen.

Und dass ich eine solche Datenstruktur in OOP mit Klassen nicht so einfach nachbilden kann wie bei SPS hab ich jetzt auch gelernt 😃

Und hilf mir mal bitte auf die Sprünge warum ich "das Pferd von der falschen Seite aufzäume" Vielleicht ist es heute einfach nur zu spät aber ich sehe meinen Denkfehler nicht

PS meine set_ und get_ geschichten sind nur an manchen stellen wo ich die eingabewerte begrenzen will
sprich ohne auf korrekten code zu achten da ich keinen Limit(min,value,max) oder ähnliches gefunden habe


Set_bla(value)
{if value > x
 merke x
 else if value < 0
 merke 0
 else
 merke value}