Hallo,
mit Bezug auf diesen Thread
Darf ich es wagen?
poste ich hier mein erstes Dokument (in diesem Forum). Ich bitte um Feedback und konstruktive Kritik. =)
Gegenseitiger Klassenzugriff
Man stelle sich folgendes Szenario vor:
Eine WinForms-Anwendung hat, unter anderem, eine Checkbox. In einer anderen Klasse soll der Status dieser Checkbox abgefragt werden, um entsprechende Aktionen durchzuführen (z.B. Änderung eines Codierungsverfahrens).
Man muß also diesen Status an die andere Klasse übergeben.
Nach Durchführung einer entsprechenden Operation soll das Ergebnis wieder in die Forms-Klasse übermitteln werden, damit sie im Form ausgegeben werden kann.
Versucht man es über normale Memberdeklaration wie in diesem Beispiel...
class Class1
{
Class2 C2Obj = new Class2();
/* Code */
}
class Class2
{
Class1 C1Obj = new Class1();
/* Code */
}
... erhält man die Fehlermeldung „infinite Loop“, was auch logisch ist. Das eine Klassenmember enthält eine Referenz auf das Andere. Dieses wiederum auf das Eine.
Hier die Lösung:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool CheckBoxFlag = false;
public string MessageText;
public bool CheckBoxFlagProperty
{
get
{
return CheckBoxFlag;
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if(CheckBoxFlag)
{
CheckBoxFlag = false;
}
else
{
CheckBoxFlag = true;
}
TestClass.CheckBoxMessage(this);
textBox1.Text=(MessageText);
}
}
class TestClass
{
public static void CheckBoxMessage(Form1 CBF)
{
if(CBF.CheckBoxFlagProperty)
{
CBF.MessageText = "flagged";
}
else
{
CBF.MessageText = "unflagged";
}
}
}
Hier sieht man mehrere Tricks (naja für Anfänger 😉 ). Im Prinzip dreht sich alles um die Bool-Variable CheckBoxFlag.
Nach deren Deklaration sieht man ein Property. Dieses wird später zu einem Teil eines Klassenmembers der Form1-Klasse.
Über diese Referenzierung wird der Inhalt bzw. der Wert von CheckBoxFlag an die Klasse Testclass übermittelt.
Im Event checkBox1_CheckedChanged wird lediglich das Flag umgesetzt, denn hier wird nur erkannt ob sich die Checkbox geändert hat, aber nicht wie!
Stand das Flag also auf true, wird es auf false gesetzt und umgekehrt.
Jetzt kommt die wirklich interessante Zeile Testclass.CheckBoxMessage(this);.
Da die Methode CheckBoxMessage static ist, braucht man keine Memberdeklaration, sondern kann sie direkt über Testclass. aufrufen.
Das eigentlich interessante hier ist aber das Schlüsselwort this. This ist quasi ein Member der eigenen Klasse und referenziert alle Mitglieder!
Wir brauchen aber doch gar nicht alle Mitglieder – jetzt kommt der zweite, interessante Teil. Schauen wir uns die Deklaration der Methode CheckBoxMessage an:
Zuerst fällt auf daß sie void ist, also gar nichts zurück gibt. Wir brauchen aber etwas zurück. Immer mit der Ruhe.
Als nächstes sehen wir, daß die Methode einen Parameter erwartet, nämlich (Form1 CBF).
Es handelt sich um ein Objekt namens CBF (kurz für CheckBoxFlag), mit dem Typ Form1. Es handelt sich hierbei also um eine Klassenmemberdeklaration der Klasse Form1.
Die übliche Deklaration mit dem Schlüsselwort new wird nicht benötigt, weil es sich hier nur um ein Empfängerobjekt handelt. Die Initialisierung erfolgt ja durch die Parameterübenahme.
Das paßt ja mit dem Methodenaufruf zusammen. Was passiert hier?
Das Objekt CBF referenziert ja wie gesagt die Form1-Klasse.
Mit CBF.CheckBoxFlagProperty wird die Property CheckBoxFlagProperty aufgerufen. Schauen wir uns diese nun an. Sie gibt lediglich den Wert von CheckBoxFlag zurück.
In eine If-Anweisung verpackt, kann nun also entsprechend des Wertes gehandelt werden.
Hinweis: if(CBF.CheckBoxFlagProperty) ist das Gleiche wie if(CBF.CheckBoxFlagProperty == true).
Die Zeile CBF.MessageText = "flagged"; (bzw. unflagged) übergibt ein Textliteral an die Variable Messagetext der Form1-Klasse.
Damit ist die Funktion der Zeile Testclass.CheckBoxMessage(this); abgeschlossen.
Zum Schluß wird der Text noch über textBox1.Text=(MessageText); im Form ausgegeben.
Man könnte die Methode CheckBoxMessage auch mit Rückgabe machen und das ganze damit vereinfachen. Was mich aber interessierte war die Möglichkeit des gegenseitigen Klassenzugriffs.
Hallo Cyron,
da du ja kontruktive Kritik hören wolltest:
Was du programmiert hast, nennt man einen Zyklus.
D.h. zwei Klassen (Form1 und TestClass) sind jeweils voneinander abhängig. Die offensichtlich angestrebte Spaltung von Funktionalität in 2 Klassen wurde zwar erreicht, bringt aber näher betrachtet gar nichts. Denn egal welche Klasse du verwendest, immer wirst du auch die andere brauchen um die jeweils andere verwenden zu können.
Das mag sicht jetzt nicht wirklich schlimm anhören, bei steigender Komplexität deines Programms wird dies aber GARANTIERT zu problemen führen.
Original von Cyron
if(CheckBoxFlag) { CheckBoxFlag = false; } else { CheckBoxFlag = true; }
So was tut doch weh...
Wie wär's mit
CheckBoxFlag=!CheckBoxFlag
Im übrigen sehe ich nicht wirklich, was es bringen soll ein Form so weiterzureichen.... Wenn schon würde ich entweder eine Methode erstellen welche ein bool entgegennimmt und einen String returniert... oder eine Methode mit 2 Inputs (Bool-Flag und Combo fürs zurückschreiben)
public string GetCheckText(bool pFlag)
{
return pFlag?"checked":"unchecked";
}
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo, ich bin's mal wieder. 😁
Wie ich es nicht machen soll, weiß ich ja nun, aber eine gute Lösung fehlt mir noch immer. Es geht mir darum, Form1 sauber zu halten. Nur der Constructor und die Eventhandler sollen verbleiben. Ich hab da nun eine Idee, weiß aber nicht ob das auch wieder Müll ist:
Wie wäre es mit einer Vermittlerklasse?
Wäre eine Singleton-Klasse dafür geeignet?
Sollte ich noch ein Interface dazwischen setzen (warum)?
Es soll so ablaufen:
Die Klasse Form1 übergibt Statusinformation an die
Mediatorklasse.
Von dort holt sich die Testklasse die benötigten Informationen und arbeitet damit.
Danach liefert die Testklasse seine Ergebnisse an die Mediatorklasse,
wo Form1 sie sich abholt.
Damit besteht keine n:m Beziehung zwischen Form1 und Testklasse, sondern nur
1:n Beziehungen zwischen Form1-MediatorClass und TestClass-MediatorClass.
Hallo Cyron,
ich beziehe mich mal auf folgende Aussage:
Eine WinForms-Anwendung hat, unter anderem, eine Checkbox. In einer anderen Klasse soll der Status dieser Checkbox abgefragt werden, um entsprechende Aktionen durchzuführen (z.B. Änderung eines Codierungsverfahrens).
Hier würde ich folgende Lösung anstreben:
Das hat folgende Vorteile:
Somit hast Du GUI von Business entkoppelt, und nur durch Events werden Statusänderungen bekanntgegeben...
Gruß
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
Original von Cyron
Wäre eine Singleton-Klasse dafür geeignet?
Es gibt keine Singleton-Klasse; nur ein Singleton Pattern. 😉
lg,
Johann
@Cyron:
Schau Dir lieber mal Pattern wie MVC oder für .NET etwas besser geeignet MVP an.
Die sind zwar im ersten Moment komplex, wenn man es aber einmal verstanden
hat, geht es recht leicht von der hand.
Vielen Dank für die tollen Tips. =) 👍
P.S.: Man müßte den Entwicklern von SharpDevelop mal stecken daß sie ihr Singleton-Class Template umbenennen sollten.
Original von John Doe
Original von Cyron
Wäre eine Singleton-Klasse dafür geeignet?Es gibt keine Singleton-Klasse; nur ein
> . 😉lg,
Johann
Ich liebe so schlaue Kommentare.
Eine Klasse, die ein Singleton ist, ist eine Singleton-Klasse.
Ein Pattern ist eben ein Entwurfsmuster.
Genauso könntest du sagen "Es gibt keine Dieselmotoren, es gibt nur Entwurfsmuster für Diesel betriebene Motoren"
e.f.q.
Aus Falschem folgt Beliebiges
*lol* 🙂)
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011