Benutzer mit den meisten Antworten
Werte aller Klassen addieren, von welchen geerbt wird

Frage
-
Hi,
folgendes Problem:
Es gibt eine Klasse A,
eine Klasse B, die erbt von A,
eine Klasse C, die erbt von B.Alle Klassen-Objekte enthalten Zahlenwerte auf einer Variablen int value.
Im Objekt von Klasse C möchte ich wissen, wie groß die Summe von valueC + valueB + valueA ist.
Die Methode zur Addition möchte ich am liebsten nur einmal schreiben, entsprechend in Klasse A,
sie soll aber dann natürlich in allen Instanzen von B und C (ggf. auch Klasse D:C, Klasse E:D,...) genutzt werden können.Wie geht das? Wie sieht das aus?
Antworten
-
Ok, dann brauchen wir nicht unbedingt eine Children Auflistung, aber eine Parent Eigenschaft.
Hier mal ein funktionierendes Beispiel. Die Klasse beinhaltet der einfachheit nur die X- Koordinate XValue, aber das Prinzip ist ja gegeben, und kann von Dir erweitert werden.
Zunächst die Klasse A:
class A { public A () { children = new CHILDREN(); } public A (int X) { XValue = X; children = new CHILDREN(); } public A (int X, A p ) { XValue = X; Parent = p; children = new CHILDREN(); } public int XValue { get; set; } public A Parent { get; set; } public CHILDREN children { get; set; } public int GetXSum () { if (Parent == null) return XValue; else return XValue + Parent.GetXSum(); } }
Hier die Hauptklasse:
class Program { static void Main (string[] args) { A a = new A(1,null); // Raum hat kein Parent A b = new A(2, a); a.children.Add(b); // Frage ob Du das überhaupt benötigst? Debug.Print(b.GetXSum().ToString()); }
Damit sollte alles möglich sein.
Du kannst jetzt auch die Klassen B,C D.. erstellen die alle von A erben und zusätzliche Eigenschaften beinhalten.
A kümmert sich um die Koordinaten.
Das sollte es gewesen sein.
Grüße
Roland
- Als Antwort markiert frank me Mittwoch, 28. Mai 2014 11:41
-
Hallo Fank,
ich bin mir da auch nicht so sicher ob ich dich richtig verstanden haben. Wenn ja sollte es in der folgender Form Funktionieren.
public interface IValueObjekt { int Wert {get; set;} int Get(); } public class A : IValueObjekt { protected IList<IValueObjekt> _valueList = new List<IValueObjekt>(); private int _Wert = 0; public int Wert { get { return _Wert;} set { _Wert = value; } } public int Get() { return _Wert + _valueList.Sum(v => v.Get()); } } public class B<T>:A where T : A { public void Add(T value) { _valueList.Add(value); } } public class C:B <B<A>> { }
Das Interface ist glaube ich jetzt nicht unbedingt nötig und der Generische Ansatz muss noch sauber Implementiert werden.
Folgender Aufruf liefert mir 6 zurück.
private void button1_Click(object sender, EventArgs e) { var a1 = new A(); a1.Wert = 1; var b1 = new B<A>(); b1.Wert = 2; b1.Add(a1); var c1 = new C(); c1.Wert = 3; c1.Add(b1); var test = c1.Get(); }
MFG
Björn
- Als Antwort markiert frank me Donnerstag, 29. Mai 2014 09:37
Alle Antworten
-
Hallo Frank,
mittels base.Eigenschaft|Methode|... kannst Du in einer abgeleiteten Klasse auf die Basisklasse der aktuellen Klasse zugreifen. Siehe dazu:
http://msdn.microsoft.com/de-de/library/hfw7t1ce.aspx
Aber so wirklich habe ich nicht verstanden, was Du haben willst. In der Regel hast Du eine Instanz KlasseC. Woher sollen die anderen Instanzen kommen und wer besetzt die Werte der Eigenschaften dieser Instanzen?
Poste bitte mal ein komplettes Beispiel, also für die Erstellung aller Instanzen, Belegung aller Werte und dazu dann auch bitte das gewünschte Ergebnis.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
class Program { static void Main(string[] args) { A a = new A(); a.myValue = 1; B b = new B(); b.myValue = 2; C c = new C(); c.myValue = 4; int summe = c.getSumme(); //Hier hätte ich gerne die Summe 7! } } public class A { public int myValue; } public class B : A { } public class C : B { }
...als Beispiel
Weiß Du was ich meine?
-
Hallo Frank,
die Instanzen der Klasse A, B und C haben doch gar nichts miteinander zu tun. Das, was Du da vorhast, kann also so nicht funktionieren.
Ich würde für den Fall, dass Du sowas machen willst, die Instanzen entweder in eine List<A> einfügen und dann über eine Schleife die Werte addieren.
private List<A> ListeDerInstanzen { get; set; } private void TuWas() { A a = new A(); a.myValue = 1; B b = new B(); b.myValue = 2; C c = new C(); c.myValue = 3; ListeDerInstanzen = new List<A>(); ListeDerInstanzen.Add( a ); ListeDerInstanzen.Add( b ); ListeDerInstanzen.Add( c ); int summe = this.AddiereWerte(); } private int AddiereWerte() { int result = 0; foreach( A element in ListeDerInstanzen ) { result += element.myValue; } return result; }
Habs jetzt nur schnell so hingeschrieben, könnten also noch Fehler enthalten sein. Du solltest aber dennoch erkennen können, was ich meine.
Es gibt sicher auch andere Wege, das Gewünschte zu erreichen, die sind aber wohl auch nicht so, wie Du dir das vorstellst :)
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Hallo Stefan,
danke schon mal, für deine Hilfe.
Dein Code funktioniert so weit, aber ich bekomme nicht das Ergebnis, welches ich benötige.Ich habe versäumt einen weiteren Zusammenhang zu erläutern (ihn auch nicht im Code dargestellt).
Es wir ein(1!) Objekt der Klasse A mit bestimmten myValue-Wert erzeugt.
Dann werden viele Objekte der Klasse B erzeugt, jedes mit individuellen myValue-Werten, jeweils als Kinder des A-Objektes.
Dann werden viele Objekte der Klasse C erzeugt, jedes mit individuellen myValue-Werten, jeweils als Kindeines bestimmten B-Objektes.
(Daher braucht wahrscheinlich A und B jeweils eine List<A> bzw List<B>?!)Was ich suche ist die Summe von c.myValue + (ElternObjekt) b.myValue + (ElternObjekt) a.myValue.
Wenn man es mit einem Baum vergleichen würde: Die Länge eines bestimmten Zweiges + Länge Ast + Länge Stamm.
Der Stamm ist für alle gleich, die Äste sind unterschiedlich lang, die Zweige sind aller verschieden lang.
www.energiewende-mach-ich-selbst.de
- Bearbeitet frank me Freitag, 23. Mai 2014 09:35
-
Hallo Frank,
das, was Du da beschreibst ist etwas völlig anderes als das, was dein Code aussagt.
Poste daher bitte ein exaktes Beispiel des Codes, wie er bei dir vorliegt und dann auch hier mit dem jeweiligen gewünschten Ergebnis.
So oder so: Die Instanzen haben nichts miteinander zu tun und Du kommst nicht umhin, per Schleife durch die Listen/Instanzen zu laufen.
Und Ja, wenn Du das so abbilden willst, musst Du jeweils eine List<X> haben und die dann durchlaufen.
Wenn Du eine Instanz mit einer List<X> hast und die Instanzen in List<X> dann wiederum Kindelemente haben, kannst Du das über eine Methode in der Klasse machen, die automatisch alle alle Instanzen in List<X> durchläuft, deren "myValue" Werte addiert und zurückgibt. Innerhalb der Schleife rufst Du dann für jede Instanz von X wieder diese Methode auf, dadurch ermittelt die Instanz dann auch die Werte derer Kindelemente, ...
Im Endeffekt müsste dafür eigentlich eine Methode in Klasse A reichen.
public class A { protected List<A> ListeDerInstanzen { get; set; } private void HoleSummeAllerWerte() { int result = 0; result = this.AddiereWerte(); ... } public int AddiereWerte() { int result = 0; foreach( A element in ListeDerInstanzen ) { result += element.AddiereWerte(); } return result; } }
List<A> wäre hier ausreichend, Du müsstest also keine List<B>, List<C>, ... aufbauen, kannst aber dennoch Instanzen von B und C in die Liste einfügen.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
- Bearbeitet Stefan FalzModerator Freitag, 23. Mai 2014 10:35
-
Es gibt kein "exaktes" beispiel meines Code, weil der Code noch nicht existiert.
Ich versuche gerade herauszufinden, wie ich es programmieren muss, damit ich mein gewünschtes Ergebnis erhalte.Vielleicht macht folgendes Beispiel mein Anliegen deutlicher:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); TuWas(); } private List<A> ListeDerInstanzen { get; set; } private void TuWas() { A a = new A(); a.myValue = 1; B b1 = new B(); b1.myValue = 2; a.listOfA = new List<A>(); a.listOfA.Add(b1); // ?? C c1 = new C(); c1.myValue = 4; b1.listOfB = new List<B>(); b1.listOfB.Add(c1); // ?? B b2 = new B(); b2.myValue = 8; a.listOfA.Add(b2); // ?? C c2 = new C(); c2.myValue = 16; b1.listOfB.Add(c2); // ?? int summe = c1.AddiereWerte(); // ich möchte 7 rausbekommen, nicht 63 } } public class A { public List<A> listOfA { get; set; } public int myValue; } public class B : A { public List<B> listOfB { get; set; } } public class C : B { public List<C> listOfC { get; set; } }
Mein gewünschtes Ergebnis ist die 7 (a.myValue + b1.myValue + c1.myValue),
also ohne b2.myValue und ihne c2.myValue.Anderes Beispiel, welches mein eigentliches Anliegen spiegelt:
Ein Raum wird von einer Ecke aus vermessen (x= 0, y = 0).
Im Raum steht ein Tisch auf Raumkoordinate x = 1,2m, y= 2,7m.
Auf dem Tisch befindet sich ein Blatt Papier auf Tischkoordinate 0,6m, y = 0,05m.
Auf dem Blatt Papier befindet sich ein Käfer auf Blattkoordinate 0,02m, y=0,15m.Ich suche nun die Entfernung (Koordinaten) des Käfers zur Raumebene (x = 1,82, y = 2.9).
www.energiewende-mach-ich-selbst.de
- Bearbeitet frank me Freitag, 23. Mai 2014 10:39
-
Hallo Frank,
Mein gewünschtes Ergebnis ist die 7 (a.myValue + b1.myValue + c1.myValue), also ohne b2.myValue und ihne c2.myValue.
das widerspricht IMO aber wieder genau dem, was Du vorher geschrieben hast.
Wenn Du nur die Werte der obersten Instanzen willst, dann addier die doch einfach!? Letztendlich ist das genau das hier:
int result = a.myValue + b1.myValue + c1.myValue;
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Hallo Frank,
Anderes Beispiel, welches mein eigentliches Anliegen spiegelt:
Ein Raum wird von einer Ecke aus vermessen (x= 0, y = 0).
Im Raum steht ein Tisch auf Raumkoordinate x = 1,2m, y= 2,7m.
Auf dem Tisch befindet sich ein Blatt Papier auf Tischkoordinate 0,6m, y = 0,05m.
Auf dem Blatt Papier befindet sich ein Käfer auf Blattkoordinate 0,02m, y=0,15m.
Ich suche nun die Entfernung (Koordinaten) des Käfers zur Raumebene (x = 1,82, y = 2.9).Du hast ein Objekt, welches andere Objekte enthalten kann. Ähnlich einem Grid in WPF. Diese Objekte können auch Instanzen von sich selbst enthalten.
In deinem Code-Beispiel fügst du die Objekte zu einer Liste hinzu. Somit kennt nun Klasseninstanz a Klasseninstanz b. Jedoch müsste b auch a kennen.
Ich habe mal ein kleines Beispiel geschrieben, wie man soetwas machen könnte:class Program { static void Main(string[] args) { Obj käfer;//Wird in dem initialisierungsblock zugewiesen Obj raum = new Obj() { Name = "Raum", X = 0, Y = 0, SubItems = { new Obj() { Name ="Tisch", X =1.2, Y=2.7, SubItems = { new Obj () { Name="Papier", X=0.6, Y= 0.05, SubItems = { (käfer = new Obj() { Name = "Käfer", X = 0.02, Y = 0.15, }) } } } } } }; double x, y; käfer.GetPosition(raum, out x, out y); Console.WriteLine("X = {0}, Y = {1}", x, y); Console.ReadKey(); } } public class Obj { public Obj() { this.SubItems = new ObservableCollection<Obj>(); this.SubItems.CollectionChanged += SubItems_CollectionChanged; } void SubItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { //Die Auflistung wurde geändert if (e.NewItems != null) foreach (Obj item in e.NewItems) { item.Parent = this;//Parent neu zuweisen (auf diese Instanz) } if (e.OldItems != null) foreach (Obj item in e.OldItems) { item.Parent = null;//Parent entfernen } } //Das Obj, welches diese Instanz beinhaltet public Obj Parent { get; private set; } //Die Koordinaten public double X { get; set; } public double Y { get; set; } //Der Name des Objekts public string Name { get; set; } //Die Liste mit den Sub-Elementen public ObservableCollection<Obj> SubItems { get; set; } //Ermittelt die Position des Elements in Bezug auf ein Elternelement public void GetPosition(Obj reletiveElement, out double x, out double y) { x = this.X; y = this.Y; if (this != reletiveElement) { //Parent nch nicht gefunden double cx, cy; this.Parent.GetPosition(reletiveElement, out cx, out cy); x += cx; y += cy;//Koordinaten des Parents auf addieren } } }
So oder so ähnlich macht es auch WinForms mit der Parent-Eigenschaft der Controls.
Tom Lambert - C# MVP
Bitte bewertet- und markiert Beiträge als Antwort. Danke.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Stefan FalzModerator Mittwoch, 28. Mai 2014 17:12
-
Hallo Frank,
Anderes Beispiel, welches mein eigentliches Anliegen spiegelt:
Ein Raum wird von einer Ecke aus vermessen (x= 0, y = 0).
Im Raum steht ein Tisch auf Raumkoordinate x = 1,2m, y= 2,7m.
Auf dem Tisch befindet sich ein Blatt Papier auf Tischkoordinate 0,6m, y = 0,05m.
Auf dem Blatt Papier befindet sich ein Käfer auf Blattkoordinate 0,02m, y=0,15m.
Ich suche nun die Entfernung (Koordinaten) des Käfers zur Raumebene (x = 1,82, y = 2.9).das ist zwar jetzt verständlich, hat aber IMHO mit beiden bisher genannten Anforderungen (zumindest aber mit der ersten) gar nichts mehr zu tun. Die Vererbung der Klassen spielt hierbei keinerlei Rolle, das ist dann eine einfache Parent-Child Beziehung.
Das Beispiel von Tom sollte das, was Du jetzt machen willst, können. Ich persönlich würde aber denken, dass es auch ohne Referenz auf den Parent geht. Aber probier es dennoch mal damit, wenn es nicht klappen sollte, meld dich nochmal hier.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Hallo Fank,
ich bin mir da auch nicht so sicher ob ich dich richtig verstanden haben. Wenn ja sollte es in der folgender Form Funktionieren.
public interface IValueObjekt { int Wert {get; set;} int Get(); } public class A : IValueObjekt { protected IList<IValueObjekt> _valueList = new List<IValueObjekt>(); private int _Wert = 0; public int Wert { get { return _Wert;} set { _Wert = value; } } public int Get() { return _Wert + _valueList.Sum(v => v.Get()); } } public class B<T>:A where T : A { public void Add(T value) { _valueList.Add(value); } } public class C:B <B<A>> { }
Das Interface ist glaube ich jetzt nicht unbedingt nötig und der Generische Ansatz muss noch sauber Implementiert werden.
Folgender Aufruf liefert mir 6 zurück.
private void button1_Click(object sender, EventArgs e) { var a1 = new A(); a1.Wert = 1; var b1 = new B<A>(); b1.Wert = 2; b1.Add(a1); var c1 = new C(); c1.Wert = 3; c1.Add(b1); var test = c1.Get(); }
MFG
Björn
- Als Antwort markiert frank me Donnerstag, 29. Mai 2014 09:37
-
Hi Tom,
ich habe dein Programm getestet, so wie es ist, und ich kann mir gut vorstellen, dass es eine gute Lösung für mein Problem sein könnt. Ich habe ein Programm geschrieben, welches meinen Anforderungen in etwa entspricht und versucht deinen Code zu implementieren. Leider scheitere ich daran, dass this.Parent am Ende null ist und ich bekomme es nicht hin, das es tut, was es soll.
hier ist this.Parent == null
this.Parent.GetPosition(reletiveElement, out cx, out cy);
offensichtlich da das Event...
SubItems_CollectionChanged()
... nie aufgerufen wird.
Ich würde mich freuen, wenn du (oder auch jemand anderes) drüber schauen könntest. Da der Code etwas umfangreicher ist, gebe ich mal den Link zum Download des Paketes an. Es handelt sich um eine zip-Datei und eine WPF-Anwendung.
Auf der Oberfläche einfach nacheinander alles ausfüllen, ich denke es erklärt sich einigermaßen selbst.
Grüße!
-
Hi Frank,
das Wurzelelement hat auch keinen Parent, das ist schon richtig so und die Abbruchbedingung für die Rekusion.
Ich hab die Methode jetzt mal so geändert, das sie einen Punkt zurück gibt, das mach die Sache einfacher.
public Point GetPosition(A reletiveElement) { if (this.Parent != null && this != reletiveElement) { var sumPositions = this.Parent.GetPosition(reletiveElement); var x = this.X + sumPositions.X; var y = this.Y + sumPositions.Y;//Koordinaten des Parents auf addieren return new Point(x, y); } return new Point(0, 0); }
MFG
Björn
-
Hallo,
du hast zwar die SubItems-Auflistung in der A-Klasse, jedoch fügst du nie die SubItems dieser Auflistung hinzu.Momentan hast du nur die 3 Klasseninstanzen a, b und c. Die einzige Gemeinsamkeit ist, dass alle in der Liste stehen.
Ich weiß nicht so ganz, was du nun genau vor hast. ich habe nur 2 Ideen, wie du dein Problem vielleicht lösen kannst:- Durchlaufe alle Elemente und addiere die dort enthaltenen Werte. Das entspricht aber nicht dem, was ich ursprünglich dachte, was du vor hast.
var summe = listOfObjects.Sum(x => x.myValue);//Summiere alle myValue-Eigenschaften per LINQ lblResult.Content = summe.ToString();
- Bei meiner 2. Idee musst du alle die Klasseninstanzen beim hinzufügen zu
listOfObjects auch zu den Parents hinzufügst. Dafür musst du allerdings die Instanzen von a und b kennen um b zu a und c zu b hinzufügen zu können.
private A baseClass = new A(); B b = new B(); C c = new C(); private void calculateSumme() { int summe; c.GetPosition(baseClass, out summe); lblResult.Content = summe.ToString(); } private void processAObject() { if (!tbxLevel1Value.Equals(warning)) { baseClass.myValue = Convert.ToInt32(tbxLevel1Value.Text); baseClass.name = "baseClass " + Convert.ToInt32(tbxLevel1Value.Text); listOfObjects.Add(baseClass); setCmsObjectNames(); btnAdd1.IsEnabled = false; } } private void processBObject() { if (!tbxLevel2Name.Equals("") && !tbxLevel2Value.Equals(warning)) { //B b = new B();//Liegt nun in der Klasse b.name = tbxLevel2Name.Text; b.myValue = Convert.ToInt32(tbxLevel2Value.Text); // listOfObjects.Add(b);//Braucht man meiner Meinung nach nicht setCmsObjectNames(); tbxLevel2Name.Text = ""; tbxLevel2Value.Text = ""; tbx_LostFocus(tbxLevel2Value, null); baseClass.SubItems.Add(b);//Zu a hinzufügen } } private void processCObject() { if (!tbxLevel3Name.Equals("") && !tbxLevel3Value.Equals(warning)) { c.name = tbxLevel3Name.Text; c.myValue = Convert.ToInt32(tbxLevel3Value.Text); // listOfObjects.Add(c); setCmsObjectNames(); tbxLevel3Name.Text = ""; tbxLevel3Value.Text = ""; tbx_LostFocus(tbxLevel3Value, null); b.SubItems.Add(c);//Zu b hinzufügen } }
Weiterhin muss die GetPosition-Methode auf myValue angepasst werden:public void GetPosition(A reletiveElement, out int x) { x = this.myValue; if (this != reletiveElement) { //Parent noch nicht gefunden int cx; this.Parent.GetPosition(reletiveElement, out cx); x += cx; } }
Den Y-Wert habe ich entfernt, weil dieser bei einem Integer nutzlos ist.
Im Ganzen weiß ich nun aber auch nicht mehr, was du vor hast. Ich kann jetzt lediglich meine Gedanken dazu nieder schreiben.
Tom Lambert - C# MVP
Bitte bewertet- und markiert Beiträge als Antwort. Danke.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets - Durchlaufe alle Elemente und addiere die dort enthaltenen Werte. Das entspricht aber nicht dem, was ich ursprünglich dachte, was du vor hast.
-
Ich möchte nochmal beschreiben was mein Ziel ist.
Gegeben sind Klasse A, Klasse B : A, Klasse C : B.
Die Vererbung ist wichtig und bei jeder Klasse kommen weitere Eigenschaften und Methoden hinzu.
Nun Beispielobjekte:
A a = new A(); a.value = 1;
B b1 = new B(); b1.value = 2; Kind von a
B b2 = new B(); b2.value = 4; Kind von aC c1 = new C(); c1.value = 8; c1 soll Kind von b1 sein !
C c2 = new C(); c2.value = 16; c2 soll Kind von b1 sein !C c3 = new C(); c4.value = 32; c3 soll Kind von b2 sein!
Nun möchte ich fragen können, wie groß der Wert eines einzelnen Ojektes vom Objekt selbst bis zum base-Objekt a ist.
int summe = getSumme(a); // 1
int summe = getSumme(b1); // 3
int summe = getSumme(b2); // 5
int summe = getSumme(c1); // 11
int summe = getSumme(c2); // 19
int summe = getSumme(c3); // 37Um die Kind-Eltern-Abhängigkeit darzustellen könnten die jeweiligen Elternobjekte Listen mit sich führen.
b1.listOfChilds.Add(c1);
b1.listOfChilds.Add(c2);Oder die Kindobjekte tragen den Objektverweis der Eltern mit sich.
c1.parent = b1; (Ich weiß nicht recht, hab so was noch nie gesehen?!)Was ich suche ist sozusagen die Logik von getSumme() (und allem, was dazu gehört, evtl. Listen, Listener,...?)
Im Moment ist das mit den drei Klassen noch übersichtlich, aber am Ende will ich einen Baum mit ca. 15 bis 25 Klassen händeln können.
Frank
-
Hallo Frank,
bitte nicht Klassen mit Objekten verwechseln!
Das haben Dir Tom und Stefan auch schon versucht zu erklären.
Was Du brauchst, ist ein Container in Deinen Klassen/Objekten, welcher die Kinder aufnimmt. Das musst Du dann aber auch explizit bei der Erstellung tun.
Bleiben wir bei Deinem Beispiel:
A a = new A(); a.value=1;
B b1 = new B(); b.value=2;
a.children.add(b1);
B b2 = new B(); b.value=4;
a.children.add(b2);
jetzt kennt das Objekt "a" alle Kinder und kann, die Gesamtsumme aller Kinder + der eigenen Werte ermitteln.
Das mir dem Container ist klar?
Grüße
Roland
-
Hi Roland,
an welcher Stelle verwechsel ich Klasse mit Objekt?
Mit dem Container meinst du die Liste aller KindObjekte, oder?
Dein Beispiel angenommen bekäme ich die Summe 6 (bzw. 7 wenn man a.value hinzunimmt). Oder verstehe ich dich falsch?
Aber ich will nicht die Summe aller Kinder(!),
sondern die Summe kind.value + eltern.value (+ grosseltern.value + ...)Beim Beispiel zu bleiben:
3 für Anfrage nach Objekt b1,
5 für Anfrage nach Objekt b2 und
1 für Anfrage nach Object a. -
Hallo Frank,
klar die Summe der Kindeskinder sind natürlich auch dabei, ich wollte mir in meinem Beispiel das aufnehmen von c.. in b.. sparen.
Aber wie gesagt hat das nichts mit Vererbung zu tun.
Natürlich kannst du eine Klasse B erstellen die von A erbt und diese in die Kette aufnehmen, das ist aber nicht nötig. Du könntest auch folgendes machen:
A a=new A(); a.value=1;
A b=newA(); b.value=2;
a.children.add(b);
....
Einfacher wird das ganz übrigens noch mit einem geeigneten Konstruktor, der value direkt übergibt, dann kann das Beispiel so aussehen:
A a = new A(1);
b= a.children.add( new A(2));
genauso könnte natürlich auch:
b= a.children.add( new B(4));
ausgeführt werden.- Bearbeitet Roland Franz Dienstag, 27. Mai 2014 07:08 zu früh gesendet.
-
Hallo Frank,
ich glaube, entweder hast Du dich ziemlich verrannt und gibst uns Infos, die uns mehr verwirren als sie uns helfen würden oder deine Erklärung hat (immer noch) nichts mit deinem Code zu tun.
Die Vererbung der Klassen ist für deine genannten Anforderungen (Eltern -> Kind Beziehung) völlig egal.
Nun möchte ich fragen können, wie groß der Wert eines einzelnen Ojektes vom Objekt selbst bis zum base-Objekt a ist.
Gar nicht. Bzw. nur Objekt.Eigenschaft. Die Vererbung spielt hier lt. deinem obigen Code keinerlei Rolle, da Du Kindelemente hast und keine jeweils eigene Eigenschaft "value" in Klasse A, B und C. Klasse A hat die Eigenschaft "value", das wars. Nicht mehr und nicht weniger.
---
Was genau verstehst Du unter "Kind von A"? Nimm bitte mal das folgende Beispiel (hier der Klassenaufbau mit Parent und Childs, damit das letztendlich das abbildet, was Du beschreibst):
public class A { protected A Parent { get; set; } public List<A> Childs { get; set; } public int Value { get; set; } public A() { this.Childs = new List<A>(); } public int SumOverChilds() { int result = 0; result = this.Value; if( this.Childs != null ) { foreach( A child in this.Childs ) { result += child.SumOverChilds(); } } return result; } public int SumOverParents() { int result = 0; result = this.Value; if( this.Parent != null ) { result += this.Parent.SumOverParents(); } return result; } } public class B : A { public B() : this( null ) { } public B( A parent ) { this.Parent = parent; this.Childs = new List<A>(); } } public class C : B { public C() : this( null ) { } public C( B parent ) { this.Parent = parent; this.Childs = new List<A>(); } }
Jetzt noch ein wenig Code, der das macht, was Du oben beschrieben hast:
public void Calculate() { A a = new A(); a.Value = 1; B b1 = new B( a ); b1.Value = 2; B b2 = new B( a ); b2.Value = 4; C c1 = new C( b1 ); c1.Value = 8; C c2 = new C( b1 ); c2.Value = 16; C c3 = new C( b2 ); c3.Value = 32; a.Childs.Add( b1 ); a.Childs.Add( b2 ); b1.Childs.Add( c1 ); b1.Childs.Add( c2 ); b2.Childs.Add( c3 ); int sumOverChilds = a.SumOverChilds(); int sumOverParents = c1.SumOverParents(); }
Was ich jetzt eingefügt habe, was aber lt. deiner Beschreibung irrelevant ist, wäre die Vererbung sowie die Childs Auflistung. Wenn Du immer nur vom Kind bis in die oberste Elternebene berechnen willst, brauchst Du nur die Parent Eigenschaft. Nur, wenn Du umgekehrt (also vom Parent aus über alle Kindobjekte und das in der gesamten Hierarchie) laufen willst, wäre die Childs Auflistung sinnvoll. Die Vererbung brauchst Du hierfür immer noch nicht.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Hallo Frank,
an welcher Stelle verwechsel ich Klasse mit Objekt?
wahrscheinlich an der Stelle, an der Du verwirrenderweise immer wieder von Vererbung und dass diese für dich sehr wichtig ist und ... sprichst, deine gesamte Beschreibung aber rein gar nichts mit Vererbung zu tun hat.
Daher gehen einige hier (inkl. meiner Wenigkeit) davon aus, dass Du denkst, dass eine Vererbung automatisch so etwas wie eine Eltern -> Kind Beziehung herstellt, die deine Anforderungen erfüllen würde. Es gibt zwar eine Hierarchie (bspw. über base) ist aber etwas ganz anderes als Du es hier brauchst.
D.h. wenn das dein einziger Grund für die Vererbung war, kannst Du die auch weglassen und ohne arbeiten. Was Du stattdessen brauchst, siehst Du in den Codebeispielen (Parent Eigenschaft) bzw. hier:
public class D { protected D Parent { get; set; } public int Value { get; set; } public D( int value ) : this( null, value ) { } public D( D parent, int value ) { this.Parent = parent; this.Value = value; } public int SumOverParents() { int result = 0; result = this.Value; if( this.Parent != null ) { result += this.Parent.SumOverParents(); } return result; } }
Verwenden kannst Du das dann so:
public void Calculate() { D d = new D( 1 ); D e1 = new D( d, 2 ); D e2 = new D( d, 4 ); D f1 = new D( e1, 8 ); D f2 = new D( e1, 16 ); D f3 = new D( e2, 32 ); int sumOverParentsD = f3.SumOverParents(); }
Der restliche Code aus meinen früheren Beispielen ist für das, was Du beschreibst, nicht notwendig. Probier es daher mal bitte mit dem hier.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
- Bearbeitet Stefan FalzModerator Dienstag, 27. Mai 2014 07:27
- Als Antwort vorgeschlagen Stefan FalzModerator Mittwoch, 28. Mai 2014 17:10
-
Hi,
ich bin nicht sicher, ob es gut ist, dass hier noch ein Koch im Brei rumrührt, aber die geposteten Beispiele erfüllen meines Erachtens die 'fachlichen Anforderungen', die du beschrieben hast. Im Gegensatz zu den anderen Köchen, mache ich hier keinen weiteren "so könnte es gehen"-Vorschlag, sondern versuche dir deinen Denkfehler zu zeigen:
Du schreibst:
Gegeben sind Klasse A, Klasse B : A...Das ist o.k.. Du schreibst weiter:
A a = new A(); ... B b1 = new B(); ... [b1 ist] Kind von aDer gefettete Teil ist FALSCH. Ein konkretes Objekt (= Instanz, hier "b1") ist niemals Kind (im Sinne von Vererbung) eines anderen konkreten Objekts (hier "a"). Das geht NUR mit Klassen (hier "A" und "B"); und Klassen haben keine (von dir benötigten) konkreten Eigenschaften. Instanzen von abgeleiteten Klassen haben geerbte Eigenschaften nur einmal. "b1" hat also die Eigenschaft "value" aber keine Eigenschaft "a.value".
Das Problem scheint mir im Wort "Objekt" zu liegen, das mal in der Bedeutung von "Klasse" und mal in der Bedeutung von "Instanz" verwendet wird.
Du suchst also Dinge, die man ineinander 'schachteln' kann. Es kann tatsächlich sein, dass ein Container die Instanz einer Klasse A ist und das 'geschachtelte Ding' Instanz einer Klasse B und dass diese Klassen sich vererbungstechnisch so verhalten, wie du es beschrieben hast, das alles ist jedoch für die Positionsberechnung irrelevant! Hierfür brauchst du Dinge, die die Eigenschaft "relative Position zum Container" haben: fertig. Diese Dinge könnten also alles Instanzen derselben Klasse sein.
Gruß
Jürgen -
Bitte schaut nicht so sehr auf meinen Code, sondern auf das was ich mit meinen Worten beschreibe.
Hätte ich den richtigen Code, dann würde ich hier nicht posten!!!Ich weiß, dass mein Problem mit der Addition nichts direkt mit der Vererbung zu tun hat.
Aber mein Softwareprojekt basiert darauf, dass ich mit einer Vererbungsstruktur arbeite.Diese Vererbung erstelle ich, da sie den Objekten in der Realität entsprechen. Es gibt eine (materielle) Arbeitsfläche (baseObject), darauf befinden sich verschiedene Objekte (Instanzen einer entsprechender Klassen, also Einheiten,...). Jede dieser Einheiten haben wiederum andere Bestandteile und Eigenschaften u.s.w. Daher Vererbung.
Nun will ich jedes Objekt fragen können: wo befindest du dich (Koordinaten). Jedes Objekt kennt aber nur die Koordinaten (= value) im Verhältnis zum direkten Elternobjekt. Also brauche ich die eigenen Koordinaten, die der Eltern bis hin zu den Koordinaten von baseObject.
Hier ein schnell zusammengeschustertes Klassendiagramm als Beispiel:
Meint ihr immer noch ich denke was falsches oder ist es nun verständlicher?
Frank
www.energiewende-mach-ich-selbst.de
- Bearbeitet frank me Dienstag, 27. Mai 2014 08:05
-
Hi Jürgen,
mir ist klar, dass Objekt b1 nicht von a erbt, sondern nur B von A.
Aber es gibt einen Zusammenhang zwischen b1 und a, den ja auch das Verhältnis der Klassen spiegeln soll.
(Siehe Klassendiagramm in meiner anderen Mail)
Jedes Objekt kann verschiedene Objekte (von erbenden Klassen) in sich tragen,
diese Objekte wiederum können auch wieder Objekte (von erbenden Klassen beinhalten) usw.Grüße, Frank
- Bearbeitet frank me Dienstag, 27. Mai 2014 08:15
-
Ok, dann brauchen wir nicht unbedingt eine Children Auflistung, aber eine Parent Eigenschaft.
Hier mal ein funktionierendes Beispiel. Die Klasse beinhaltet der einfachheit nur die X- Koordinate XValue, aber das Prinzip ist ja gegeben, und kann von Dir erweitert werden.
Zunächst die Klasse A:
class A { public A () { children = new CHILDREN(); } public A (int X) { XValue = X; children = new CHILDREN(); } public A (int X, A p ) { XValue = X; Parent = p; children = new CHILDREN(); } public int XValue { get; set; } public A Parent { get; set; } public CHILDREN children { get; set; } public int GetXSum () { if (Parent == null) return XValue; else return XValue + Parent.GetXSum(); } }
Hier die Hauptklasse:
class Program { static void Main (string[] args) { A a = new A(1,null); // Raum hat kein Parent A b = new A(2, a); a.children.Add(b); // Frage ob Du das überhaupt benötigst? Debug.Print(b.GetXSum().ToString()); }
Damit sollte alles möglich sein.
Du kannst jetzt auch die Klassen B,C D.. erstellen die alle von A erben und zusätzliche Eigenschaften beinhalten.
A kümmert sich um die Koordinaten.
Das sollte es gewesen sein.
Grüße
Roland
- Als Antwort markiert frank me Mittwoch, 28. Mai 2014 11:41
-
Hi,
dann braucht jede der in Frage kommenden Klassen eine Eigenschaft "Container" (oder "Parent" wie in den Beispielen oben) und eine Listen-Eigenschaft "Contained" (oder "Children" wie oben). Der Einfachheit halber kannst du diese Eigenschaften in "Arbeitsfläche" implementieren; ich würde mir (nach dem vermuteten Sinn der angezeigten Namen) hierfür eine neue Klasse mit den genannten Eigenschaften und "Point3D" erstellen und "Arbeitsfläche" davon ableiten. Der Container ist vom Typ "Arbeitsfläche" (bzw. "neue Klasse"). Beim Erzeugen der verschiedenen Instanzen bekommen diese mitgeteilt, in welchen Container sie eingefügt werden...
var tasse = new Tasse(this);
this.Contained.Add(tasse);...und dann kann jedes Element über Rekursionen (wie oben) seine Position im 'äußersten' Container bestimmen (skizziert):
var point = this.Point3D;
var container = this.Container;
while(container != null)
{
point = point + Container.Point3D; // vereinfacht; bitte korrekt addieren
container = container.Container;
}Dann steht in "point" die Position des abgefragten "Ding" zu dem Container, der selbst nirgendwo enthalten ist. Die Abfrage "container != null" kannst du auch so abändern, dass du die Position in einem bestimmten Container zurückgeliefert bekommst.
Mist, nun habe ich doch einen weiteren "so-könnte-es-gehen" Vorschlag gemacht.
Gruß
PS: Ich bin nicht davon überzeugt, dass du diesen Vererbungsbaum brauchst. Jedenfalls nicht für die gezeigten Vorschläge. Das Entscheidende hierfü ist, dass alle gelisteten Klassen von der Klasse mit den Eigenschaften "Container", "Contained" und "Point3D" abgeleitet sind. Sie müssen nicht alle aufeinander aufbauen (es reichen also zwei Ebenen im Vererbungsbaum). Der Baum kann jedoch durch andere, hier nicht genannte Anforderungen trotzdem nötig sein.
Jürgen- Bearbeitet Jürgen Röhr Dienstag, 27. Mai 2014 08:39
-
...und hier noch ein Beispiel mit einer geerbten Klasse:
class Program { static void Main (string[] args) { A a = new A(1,null); // Arbeitsfläche hat kein Parent FIXESGERAET b = new FIXESGERAET(); b.Parent = a; // von A geerbt b.XValue = 2; // von A geerbt b.Color = "red"; // dies Eigenschaft hat nur FixesGeraet Debug.Print(b.GetXSum().ToString()); } }
GetXsum ist bei Dir natürlich GetPoint mit den X,Y und Z Koordinaten ;-)
- Bearbeitet Roland Franz Dienstag, 27. Mai 2014 08:48
-
Hallo Frank,
Diese Vererbung erstelle ich, da sie den Objekten in der Realität entsprechen. Es gibt eine (materielle) Arbeitsfläche (baseObject), darauf befinden sich verschiedene Objekte (Instanzen einer entsprechender Klassen, also Einheiten,...).
und dazu passen die Beispiele hier, die mit einer Parent Eigenschaft arbeiten. Gibt es dabei Verständnisprobleme? Falls ja, welche genau?
Aber lass bitte das "erbende Klasse", ... bei deiner weiteren Beschreibung weg. Das verwirrt nur und hat nichts mit deiner Fragestellung zu tun.
Eigentlich hast Du eine klassische Parent->Child Struktur, bei der das Kind auch den Eltern Part kennt. Da Du darauf beharrst, dass Du niemals vom Parent durch die Childs laufen willst, kannst Du die Childs Auflistung auch weglassen und nur mit der Parent Eigenschaft arbeiten, ich persönlich würde sie drin lassen.
Beispiele hast Du ja jetzt zuhauf, insbesondere die letzten paar passen zu deinen Anforderungen.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Ich denke ich hab's. ;)
Vielen Dank Euch allen, für Eure Hilfe und Geduld.
Tut mir leid, dass ich mich so schwer getan habe.
Hier mein Code (angelehnt an Rolands Beispiel) für andere mit selben Problem direkt mit Ausgabe auf Konsole:
class Program { static void Main(string[] args) { A a = new A(1, null); B b1 = new B(2, a); B b2 = new B(4, a); C c1 = new C(8, b1); C c2 = new C(16, b1); C c3 = new C(32, b2); C c4 = new C(64, b2); string br = "\n"; string result = "a: " + a.GetXSum() + br + "b1: " + b1.GetXSum() + br + "b2: " + b2.GetXSum() + br + "c1: " + c1.GetXSum() + br + "c2: " + c2.GetXSum() + br + "c3: " + c3.GetXSum() + br + "c4: " + c4.GetXSum(); Console.WriteLine(result.ToString()); } } class A { public A() { } public A(int X, A p) { XValue = X; Parent = p; } public int XValue { get; set; } public A Parent { get; set; } public int GetXSum() { if (Parent == null) return XValue; else return XValue + Parent.GetXSum(); } } class B : A { public B() { } public B(int X, A p) { XValue = X; Parent = p; } private string getColor() { return "red"; } } class C : B { public C() { } public C(int X, A p) { XValue = X; Parent = p; } }
www.energiewende-mach-ich-selbst.de
- Bearbeitet frank me Mittwoch, 28. Mai 2014 11:41