PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Polymorphie


grakaman
2003-04-10, 18:46:23
Hi

Ich hab da ein kleines Problem. Ich habe eine Klasse (C#), die die sich von der Klasse System.Web.UI.Page ableitet. Diese Klasse besitzt bestimmte Ereignismethoden, speziell ist hier die Rede von der Methode Page_Load. In dieser Methode führe ich bestimmten Code aus. Dann habe ich noch eine weitere Klasse, die von der vorhergehenden erbt. In dieser Klasse möchte ich ebenfalls wieder die Ereignismethode Page_Load verwenden. Zusätzlich zu dem Code, der in der Methode steht, möchte ich, dass auch der Code aus der Basisklasse ausgeführt wird. Am Anfang hatte ich in der Basisklasse das virtual Schlüsselwort benutzt und die Methode in der geerbten Klasse mit override überschrieben. Zusätzlich benutzte ich noch base.Page_Load(sender, e), damit auch der Code in der Basisklasse ausgeführt wird, das sah dann so aus:

protected override void Page_Load(object sender, System.EventArgs e)
{
base.Page_Load(sender, e);
Response.Write("Test");
}

Zwar führt er den Code der Basisklasse ohne Probleme aus, aber aus irgend einen Grund führt er den Code der überschriebenen Methode zwei mal aus. In dem Fall schreibt er also zwei mal "Test" auf den Bildschirm. Ok, nun habe ich mal das virtual und override beider Klassen gelöscht und in der erbenden Klasse das Schlüsselwort new vor der Methodendeklaration geschrieben. Soweit funktioniert jetzt auch alles, weil er glaub ich das einfach ignoriert und beide getrennt ausführt. Aber ich bin mir nicht so sicher, ob das eine gute Lösung ist. Gibts nicht doch ne Möglichkeit die Methode zu überschreiben, ohne mit den obigen Effekten?

MfG

Demirug
2003-04-10, 18:59:22
Ich glaube du bist da in eine Falle bezüglich des Event handlings bei .net gelaufen.

kann es sein das du in deinem Code zweimal was in der folgenden Art hast und zwar einmal in der Basisklasse und einmal in der abgeleiteten?


this.Load += new System.EventHandler(this.Form_Load);

grakaman
2003-04-10, 19:00:30
jo, hab ich

Demirug
2003-04-10, 19:08:58
In dem Fall es einfach bei den zwei unabhängigen Methoden belassen. Bei Events ist das schon OK so.

grakaman
2003-04-10, 19:17:00
Und welche von beiden wird dann zuerst ausgeführt? Ich nehme mal an Basisklasse oder?

MfG

Demirug
2003-04-10, 19:25:30
Originally posted by grakaman
Und welche von beiden wird dann zuerst ausgeführt? Ich nehme mal an Basisklasse oder?

MfG

Das ist nicht garantiert. Beim Eventverfahren geht es ja nur darum das eine Nachricht an mehrer Ziele vermittelt werden kann.

Wenn du davon abhängig bist das etwas in einer bestimmten Rheienfolge erledigt wird musst du anders vorgehen.

In der Basisklasse den Eventhandler einbauen und aus diesem eine virtuelle Methode aufrufen welche man dann wie gwohnt überschreiben kann.

grakaman
2003-04-10, 19:44:37
Hallo Demirug,

aber genau das hab ich ja zuerst gemacht. Ich hab hier mal meinen Code auf das wesentlich reduziert:

// Die Basisklasse

public class Class1 : System.Web.UI.Page
{
protected virtual void Page_Load(object sender, System.EventArgs e)
{
Response.Write("Ich bin die Basisklasse");
}

override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}

protected virtual void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
}

// Hier meine geerbten Klasse

public class WebForm1 : Class1
{
protected override void Page_Load(object sender, System.EventArgs e)
{
base.Page_Load(sender, e);
Response.Write("Und ich bin erbe");
}

override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}

protected override void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
}

Das Ereignis OnInit wird hierbei automatisch immer aufgerufen.
Wenn ich disen Code nun ausführe schreibt er mir zwei mal hinter einander die String aus der Basisklasse und der abgeleiteten Klasse, also:

Ich bin die Basisklasse Und ich bin erbe Ich bin die Basisklasse Und ich bin erbe

MfG

Originally posted by Demirug
In der Basisklasse den Eventhandler einbauen und aus diesem eine virtuelle Methode aufrufen welche man dann wie gwohnt überschreiben kann.

Demirug
2003-04-10, 19:58:12
// Die Basisklasse

public class Class1 : System.Web.UI.Page

protected virtual void MyPageLoad(object sender, System.EventArgs e)
{
Response.Write("Ich bin die Basisklasse");
}

protected void Page_Load(object sender, System.EventArgs e)
{
MyPageLoad (sender, e);
}

override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}

protected virtual void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
}

// Hier meine geerbten Klasse

public class WebForm1 : Class1
{
protected override void MyPageLoad(object sender, System.EventArgs e)
{
base.Page_Load(sender, e);
Response.Write("Und ich bin erbe");
}

override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
}


So meinte ich das

grakaman
2003-04-10, 20:18:19
Mhhm, da bekomme ich ständig nur eine System.StackOverflowException

grakaman
2003-04-10, 20:18:49
Mhhm, mit dem Code bekomme ich ständig nur eine System.StackOverflowException.

MfG

Demirug
2003-04-10, 20:22:02
Originally posted by grakaman
Mhhm, mit dem Code bekomme ich ständig nur eine System.StackOverflowException.

MfG

Merkwürdig. Hast du mal im Debugger geschaut durch welche Methoden er da immer wieder läuft?

grakaman
2003-04-10, 20:23:09
Tracing zeigt mir an, dass die Ausnahme am Ende der OnInit geworfen wird.

MfG

Demirug
2003-04-10, 20:34:57
nimm mal den OnInit aus der geerbten Klasse raus. Der ist ja sowieso zuviel.

grakaman
2003-04-10, 20:41:57
Nein, der Fehler ist, dass du in der override myPageLoad noch mal die base.Page_Load aufrufst. Die Page_Load ruft aber in der Basisklasse die MyPageLoad auf und somit gibts quasi ne Schleife und nen Speicherüberlauf ;)

MfG

Demirug
2003-04-10, 20:43:44
Originally posted by grakaman
Nein, der Fehler ist, dass du in der override myPageLoad noch mal die base.Page_Load aufrufst. Die Page_Load ruft aber in der Basisklasse die MyPageLoad auf und somit gibts quasi ne Schleife und nen Speicherüberlauf ;)

MfG

Copy und Paste Fehler :D

grakaman
2003-04-10, 20:49:27
Gut, ich habs in base.MyPageLoad(sender, e) abgeändert. Funktioniert auch :) Aber da bin ich halt jetzt unflexibel oder? Ich mein, ich muss doch jetzt genau schon in der Basisklasse wissen an wieviel weitere ich das vererbe?

MfG

Demirug
2003-04-10, 20:52:42
Originally posted by grakaman
Gut, ich habs in base.MyPageLoad(sender, e) abgeändert. Funktioniert auch :) Aber da bin ich halt jetzt unflexibel oder? Ich mein, ich muss doch jetzt genau schon in der Basisklasse wissen an wieviel weitere ich das vererbe?

MfG

Wieso? Du kannst doch soviele erben dazufügen wie du möchtest dafür ist die Funktion ja virtuel.

Ich frage mich sowieso was du da genau machst was zwingend voraussetzt das zuerst die Basis und dann die erben ausgeführt werden?

grakaman
2003-04-10, 21:02:19
Gut, mit einer weiteren Ableitung funktioniert das auch. Ich hab nur noch nicht so recht verstanden, warum der Umweg über die zweite Methode, MyPageLoad, gegangen werden muss???
Nun ja, müssen muss ich das nicht :D, aber ich wollte halt immer die selbe Ereignismethode nehmen, weils halt vom Kontext her ins selbe Ereignis gehört, meiner Meinung. Allerdings ist die Reihenfolge der Ausführung auf jeden Fall schon wichtig, da die abgeleitete Klasse sich auf die Member der Basisklasse bezieht.

MfG

Demirug
2003-04-10, 21:12:29
Originally posted by grakaman
Gut, mit einer weiteren Ableitung funktioniert das auch. Ich hab nur noch nicht so recht verstanden, warum der Umweg über die zweite Methode, MyPageLoad, gegangen werden muss???

Das hängt mit dem Prinzipien von delegates und events zusammen. Man könnte das ganze auch so lösen das man den delegate in einer virtuelen Methode erzeugt. Es kommt aber im Prinzip aufs gleiche raus.


Nun ja, müssen muss ich das nicht :D, aber ich wollte halt immer die selbe Ereignismethode nehmen, weils halt vom Kontext her ins selbe Ereignis gehört, meiner Meinung. Allerdings ist die Reihenfolge der Ausführung auf jeden Fall schon wichtig, da die abgeleitete Klasse sich auf die Member der Basisklasse bezieht.

MfG

Auf die Member kannst du dich ja beziehen. Problematisch wird es nur wenn die Basisklasse und die vererbten schreibend auf die gleiche Elemente zugreifen bzw die Basisklasse was schreibt was die vererbten wieder auslesen.

Wenn du solche beziehungen hast musst du dir eben wie gezeigt weiterhelfen.

grakaman
2003-04-10, 21:24:31
Gut, hast mir sehr weitergeholfen, danke :) Ich schau mir das mit den Delegates noch mal genauer an.

MfG