Laden...

Kann ich in vererbten Klassen mehrmals den gleichen Methodennamen verwenden?

Erstellt von Frokuss vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.374 Views
F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren
Kann ich in vererbten Klassen mehrmals den gleichen Methodennamen verwenden?

Hey hey 😃

ich bin in der Vererbung noch nicht so fest (wie in so manchen anderen Themen...). Mein Kompiler hat mir allerdings eine Warnung geworfen (kann man häufig auch ignorieren), wollte mich aber nur Grundversichern, dass das trotzdem stimmig ist...

Ich bin grade dabei eine Liste (List) zu erstellen, die Listeneinträge (ListElement) enthalten kann. Auch kann diese Liste genau eine Kopfzeile (ListHeadline) enthalten.

Das ListHeadline Objekt erbt hier vom ListElement. Allerdings habe ich einige Methoden, die in beiden Objekten vorkommen - und das wirft mir eine Warnung.

Folgend sieht mein Code aus:

	public class ListElement : Label{
		//Konstruktor und so...
		public void Update(sTextStyle ts){
			textStyle = ts;
			Font = textStyle.GetFont();//ListElement (Label) bekommt einen Font zugewiesen
		}
	}

	public class ListHeadline : ListElement{
		//Konstruktor und so...
		public void Update(sTextStyle ts){
			ts.SetBold(isBold);
			base.Update(ts);
		}
	}

So, warum mache ich das ganze? Wenn ich z.B. die Schriftart ändere, soll das für alle Elemente gelten. Trotzdem soll das ListHeadline-Element weiterhin dick formatiert bleiben...

Daher folgende Fragen:
1.) Kann ich das so machen, oder ist das "unterste Schubladen"-Programmieren?
2.) Gibt es anonsten andere sinnvolle / sinnvollere Umsetzungen? Ich meine... ich könnte ja auch in ListHeadline die Methode umbenennen... Aber gewiss nicht sinnvoll, oder?

Vielen Dank auf jeden Fall 😃
Frokuss

16.807 Beiträge seit 2008
vor 4 Jahren

kann man häufig auch ignorieren

Ein Compiler warnt i.d.R. nicht umsonst...

Im Prinzip brauchst Du das alles gar nicht, wenn Du DataBindings verwenden würdest.
Das funktioniert auch einwandfrei mit Fonts.

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren

Cool danke dir!

Von diesem DataBinding habe ich jetzt grade zum ersten mal gehört. Danke!

Puhh... Das macht mich ein wenig fertig...: http://openbook.rheinwerk-verlag.de/visual_csharp_2010/visual_csharp_2010_21_002.htm

Einmal zum Verständnis... mit nem Beispiel:

  • Also angenommen ich hätte jetzt eine Datenbank aus der ich alle Daten bekommen würde...
  • Ich habe zwei verschiedene Request zur Datenbank...
    • Gruppen: Freunde, Lernend und Arbeitend
    • Kontakte: Peter Pan und Santa Klaus
      • Peter Pan ist Student
      • Santa Klaus ist Familie und Arbeitend

Dann kann ich also über dieses Binding eine Verbindung zwischen der Datenbank und meinem (z.B.) Form-Objekt halten?
Also z.B. nur auf das Text-Attribut betrachtet: Ich habe dieses Binding mit meinem List-Objekt. Dann würde sich der Angezeigte Text (hier über das ListElement, mit den Einstellungen aus meinem ListHeadline) der Gruppe ändern, wenn ich den Datensatz in der Datenbank ändere, richtig? Und dieses Element kann ich dann über ein anderes Binding immer Fett dargestellt lassen? Das würde dann also quasi solange ich will "konstant" gehalten werden?

Und dann kann ich in den jeweiligen Listen die Kontakte hinzufügen und auch hier wieder den Text verbinden? Und wenn ich dann Santa Klaus Namen ändere, würde dieser auch in beiden Listen ändern?

Sorry wenns grade kompliziert ist - aber das Beispiel habe ich mir grade nur so ausgedacht...

Hoffe ihr könnt mir da weiterhelfen 😃

Frokuss

16.807 Beiträge seit 2008
vor 4 Jahren

Dann kann ich also über dieses Binding eine Verbindung zwischen der Datenbank und meinem (z.B.) Form-Objekt halten?

Nein. Die UI hat niemals Kenntnis zur Datenbank.
[Artikel] Drei-Schichten-Architektur

Du erstellst ein Binding, und gibst das mehreren Controls.
Aktualisierst Du das Binding, werden auch alle Controls aktualisiert, die das Binding verwenden.

Das bedeutet, dass Du nicht das Control zum Aktualisieren anfassen musst, sondern eben das Binding.
Siehe auch MVP (oft in WinForms verwendet) bzw. MVVM Pattern (typischer Pattern für WPF/Angular..).

Was Du da mit dem OOP gemacht hast ist im Prinzip nichts anderes als ein schmutziger Workaround, weil Du kein DataBinding kanntest. OOP ist aber prinzipiell bei diesem Vorgehen gar nicht relevant; es geht ums Binding.
In WPF wird man quasi zum Binding gezwungen; bei WinForms leben leider die meisten Leute mit Hacks und Workarounds, weil kein Binding Pattern zum Einsatz kam.

Da Du Binding noch nicht gehört hast vermute ich, dass Du bisher auch nicht wirklich ein Tutorial oder gar ein Buch durchgearbeitet hast.
Du musst Dir die Grundlagen der Technologien aneignen, damit Du damit arbeiten kannst. Ansonsten wirst Du quasi von Wand zu Wand rennen.

Fang Stück für Stück an.
Wenn Du gleich alles auf einmal machen willst, dann wird Dir das womöglich schnell über den Kopf wachsen.

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren

Edit:

Ich bin noch teilweise dabei da sganze zu lesen - komme da nicht ganz so mit der ganzen Literatur - der von mir gepostete Artikel scheint einiges zu beantworten...

Ersteinmal vielen Dank für deine Mühe 😃

Allerdings hat mir der 3-Schichten Artikel nicht wirklich weitergeholfen 😦 Was mir z.B. dort fehlt ist, wie ich exakt die Schichten trennen kann.. Lagere ich diese in einen eigenen Thread aus? Auch fehlen mir da einige weitere nützliche Infos wie:

http://www.mrknowing.com/2013/11/08/wie-funktioniert-die-3-schichten-architektur/

Grafik Schicht – GUI

Hier werden alle Steuerelemente und grafischen Komponenten platziert. Zu dem werden die Event-Handler (Button-Click, Mouse-Over usw.) definiert. In den Events werden jedoch selber keine Berechnungen vorgenommen. Diese rufen lediglich die Funktionen aus dem Logik-Layer auf.

Ich hoffe der Verweis auf den Artiekl war eher ein "Versicht, bei der DEnkweise hast du das SChichten-Modell verletzt" 😄

Nur der Artiekl hat mich nun ein wenig verwirrt... Deswegen mal etwas Code (der komplette liegt bei 160 Zeilen) aus meinem aktuellen Projekt:

	public class List : Panel{
		sTextStyle LE_textStyle;//Ansammlung von diversen Bool-Angabe (z.B: isBold, isItalic...)
		sStyleEffect LE_styleEffekt;//Ansammlung von diversen Bool-Angaben (z.B: dragable, hover..)
		
		bool status_isMini = false;//ist die Liste Minimiert (nur die Überschrift zu lesen)
		
		public ListHeadline objChildsHeadline = null;
		public Dictionary<string, List> objChildsL = new Dictionary<string, List>();//Liste in einer Liste
		//public Dictionary<string, ListElement> objChildsLE = new Dictionary<string, ListElement>();
		public OrderedDictionary objChildsLE = new OrderedDictionary();//erste Verwendung (25.04.19)
		
		public List(sTextStyle ts, sStyleEffect se, string headline = ""){
			LE_textStyle = ts;
			LE_styleEffekt = se;
			
			if(!headline.Equals(string.Empty))
				Add(headline);
			
			this.Resize += new EventHandler(Evt_Resize);//auch gepostet
		}

		//Fügt ein ListElement der Liste hinzu
		public void Add(string txt, string id){
			ListElement le = new ListElement(txt, LE_styleEffekt, LE_textStyle, id);
			le.Width = Width - Styles.ListElementEinruecken;
			
			objChildsLE.Add(id, le);
			Controls.Add(le);
			
			PositionAnpassen();//auch gepostet
		}

		//Positioniert das ListenElement an der richtigen Position - müsste daher ein Bruch mit der Aritektur sein? (Da berechnungen stattfinden...
		public void PositionAnpassen(){
			int top = 0;
			if(objChildsHeadline != null)
				top = objChildsHeadline.Height;
			
			if(objChildsL.Count > 0){
				foreach(KeyValuePair<string, List> l in objChildsL){
					l.Value.Top = top;
					top += l.Value.Height;
				}
			}
			
			if(objChildsLE.Count > 0){
				foreach(DictionaryEntry item in objChildsLE){
					((ListElement)(item.Value)).Top = top;
					top += ((ListElement)(item.Value)).Height;
				}
			}
			
			Height = top;
			
			if(Parent.GetType().Equals(typeof(List))){
				List listy = (List)Parent;
				listy.PositionAnpassen();
			}
		}

		//Auch hier mache ich Berechnungen...
		private void Evt_Resize(object sender, EventArgs evt){
			foreach(KeyValuePair<string, List> l in objChildsL){
				l.Value.Width = Width - Styles.ListElementEinruecken;
			}
			
			foreach(KeyValuePair<string, ListElement> kvp in objChildsLE){
				kvp.Value.Width = Width - Styles.ListElementEinruecken;
			}
		}

Sorry, wenn ich also jetzt vom eigentlichen Thema abweiche...

Ich glaube insgesamt, dass ich zumindestens die Daten-Schicht bisher immer gut getrennt hatte - allerdings die Logik und die Grafik-Schicht nicht so sauber... Hatte z.B. eine Klasse in der ich die komplette MySQL-Abwicklung hatte (Select, Update, Insert).

Lieben Gruß
Frokuss

PS: Habe einige Kommentare hinzugefügt...

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren

Also, ich glaube ich habe ein wenig was verstanden... Ich versuche das mal in meinen Worten zu erläutern. nur noch fix vorab... Ich denke euch ist klar, das ich nicht aus der Branche komme und das ganze nur mache, weil mir das irgendwie SPass macht - ist halt ein komisches Hobbie 😄

Beispiel Browser:
1.) Programmstart --> öffnet das Fenster höhöhö
2.) Fenster instanziert alles was fest im Code ist... Hintergrundfarbe, Überschrift, jede Gliederung von Elementen (z.B. im Tab-Leiste, URL-Leiste und Webseiten-Anzeigebereich).
3.) Der Fenster-Konstruktur ist nen bischen hungrig und will Daten haben: Daher wird hier das Objekt Start-Logik instanziert.
4.) In der Start-Logik wird dann die Methode Welche_Tabs_Sind_zu_öffnen() auf.
5.) Die wiederum instanziert das Objekt Start-Daten.
6.) Dort wird dann die Methode Letzte_Tab_Sitzungen() aufgerufen.
7.) Die Methode Letzte_Tab_Sitzungen() öffnet daher nen Reader und liest ne File aus.

Die Infos fließen dann natürlich Rückwärts. Das bedeutet die Daten aus Start-Daten.Letzte_Tab_Sitzungen() in Start-Logik.Welche_Tabs_Sind_zu_öffnen() interpretiert werden und damit irgendetwas tolles gemacht wird.
Dies könnte z.B. sein, dass also 3 Tabs geöffnet werden müssen.... Und hier stehe ich auf dem Schlauch... Übergebe ich diese Daten nun an das Fenster? Oder erzeugt die Start-Logik.Welche_Tabs_Sind_zu_öffnen() nun die 3 Tabs und fügte diese hinzu?

Um das ganze jetzt noch mit einem Event abzurunden:
Wenn ich als User auf dieses + (neuer Tab) klicke, setze ich oben quasi in 3.) an.
4b.) Start-Logik hat nun die**_ Erzeuge_Leeren_Tab()_**
fertig 😄 ...brauche ja keine Daten. Oder zählt sowas wie Tab-Breite als Daten?

Hoffe das Beispiel ist verständlich ^^

Gruß Frokuss

16.807 Beiträge seit 2008
vor 4 Jahren

Also Feedback: Dein Code ist sehr komplex zu lesen.
Du solltest Dich an die Code Guidelines und Formatierung von C# halten. Das macht es auch potentiellen Helfern einfacher.
Sowohl Visual Studio wie auch Visual Studio Code unterstützen Dich bei der automatischen Formatierung von Code.

List ist eine Klasse, die sehr sehr häufig in C# verwendet wird. Es ist unpraktisch, so eine eigene Klasse zu nennen.
Nenne sie doch in diesem Zusammenhang ListPanel, wenn Du eh schon von List erbst.
Auch die Namen der Eigenschaften sind eher Denglisch und so nicht üblich in C#. Du scheinst evtl. von PHP zu kommen..?

Was mir z.B. dort fehlt ist, wie ich exakt die Schichten trennen kann.. Lagere ich diese in einen eigenen Thread aus?

Architekturpattern wie die Schichtentrennung haben keine direkte Auswirkung auf Runtime-Eigenheiten - hat also erst mal nichts mit irgendwelchen Threads zutun.
Architekturen wirken sich darauf aus, wie Dein Quellcode organisiert ist (oder im Sinne der IT wie Deine Applikationen und die Infrastruktur aufgebaut sind).

UI-Technologie hat zB. in Logik und Datenbank nichts zu suchen; damit machst Du Dich flexibler die Logikbausteine in mehreren Technologien (WinForms, WPF, Web..) nutzen zu können.
Gleiches bei der Datenbank: Die Logikschickt als Beispiel interessiert sich nicht, ob Du MSSQL oder MySQL verwendest. Die Logikschicht will nur ein Interface haben, über das es Dinge speichern kann.
Ob Du dann Datenbank A oder B ansprichst: interessiert die Logik nicht.

Man muss es aber prinzipiell mit Pattern auch nicht übertreiben und darf durchaus an gewissen Stellen, sofern es nicht weh tut, pragmatisch bleiben.

In der Start-Logik wird dann die Methode Welche_Tabs_Sind_zu_öffnen() auf.

Und das eben nicht.

Prinzipiell stellst Du nur Informationen aus der Logikschicht bereit, die nachher die UI anzeigen soll.
Die Logikschicht kennt die UI-Technologie nicht, daher kann sie auch keine Tabs öffnen.

Ansonsten kann ich Dir ehrlich gesagt nicht ganz sooo folgen.

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren

Jep, ich habe relativ lange mit PHP gearbeitet... Da mischt man dann gerne das ganze mit HTML 😄

Was mein Beispiel angeht:

4.) In der Start-Logik wird dann die Methode Welche_Tabs_Sind_zu_öffnen() auf.

Ich hatte eigentlich auch nicht gemeint, dass dort die Daten beschafft werden...

Dies könnte z.B. sein, dass also 3 Tabs geöffnet werden müssen.... Und hier stehe ich auf dem Schlauch... Übergebe ich diese Daten nun an das Fenster? Oder erzeugt die Start-Logik.Welche_Tabs_Sind_zu_öffnen() nun die 3 Tabs und fügte diese hinzu?

Sprich mit deiner Antwort würde ich also aus der Logik die Daten an die UI übergeben - so dass dort nichts mehr gemacht werden muss als die Parameter zuzuweisen...

DIeses Binding werde ich mir auf jeden Fall noch ansehen - aber nicht mehr heute.. kurze Nacht und nen langen Tag gehabt ^^

Danke Frokuss