Hallo,
ich habe mich mal ins Thema Interfaces eingelesen.
Nun übe ich anhand von einem wirklich sehr simplen Spiel, es gibt 4 verschiedene "Zellen". Diese Zellen erben von einer Zellbasis.
public abstract class CommonCell{}
Jede Zelle enthält Informationen und implementiert durch das Interface Methoden.
Alle erzeugten Zellen werden in einer Liste gespeichert. In der Klasse, wo sich auch die Liste mit den Zellen befindet, möchte ich jede einzelne Zelle ansprechen und eine Methode aufrufen.
An die Methode müsste ich doch gelangen, da durch das Interface sichergestellt ist, dass diese Methode vorhanden ist. Ich weiß aber nicht so recht, wie ich die foreach-Schleife aufzubauen habe.
// Cells ist die Zell-Liste
foreach(Cell c in Cells)
{
c.Methode();
}
Wie muss ich "Cell c" schreiben, das gibt es nicht, ich habe nur die abstrakte Basis und die Kinder Zelle1, Zelle2, Zelle3, Zelle4.
Also quasi eine allgemeine Referenz zu allen Zellen und darüber der Methodenaufruf..
Ich stehe da grade ein wenig auf dem Schlauch.
Guten Morgen,
Du erzeugtst eine Liste mit deinen Zellen.
also:
List<Cell> cellList = new List<CommonCell>();
und dann kannst du die Liste befüllen mit:
cellList.Add(new Zelle1);
cellList.Add(new Zelle2);
cellList.Add(new Zelle3);
cellList.Add(new Zelle4);
Dann kannst du mit foreach durch die Liste iterieren.
Zuerst einmal ist eine abstrakte Klasse kein Interface. Das mag wie Haarspalterei erscheinen, aber die Konzepte "abstrakte Superklasse" und "Interface" sollte man sauber auseinanderhalten. Schon allein, weil es da sprachlich ansonsten Missverständnisse gibt.
Zum zweiten: deine Zell-Liste ist vom Typ List<CommonCell>?
Dann:
foreach(CommonCell cell in Cells)
{
cell.Methode(); //<- Wikipedia: Polymorphie lesen & verstehen.
}
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Moment. Sorry. Ich kam vielleicht sehr unverständlich rüber.
Die Liste ist schon vorhanden, so wie du gesagt hast @panicJonny.
@LaTino das hatte ich falsch ausgedrückt. Ich habe ein Interface und diese abstrakte Klasse.
Dann versuche ich es nochmal zu beschreiben, ich habe die Basis
public abstract class CommonCell
{
// ist aktuell noch leer
}
dann habe ich noch das Interface
public Interface ICell
{
void Methode1();
void Methode2();
}
Und dann habe ich noch verschiedene Zellen.
public class Zelle1 : CommonCell, ICell
{
public void Methode1()
{
// Tue dies
}
public void Methode2()
{
// Tue jenes
}
}
public class Zelle2 : CommonCell, ICell
{
public void Methode1()
{
// Tue dies
}
public void Methode2()
{
// Tue jenes
}
}
Und diese Zellkinder liegen in einem Store. Dieser Store hält folgendes:
public class Store
{
private List<Cell> cells = new List<Cell>(); // Wird gefüllt
private void ActivateCells()
{
foreach(Cell c in cells)
{
c.Methode1();
c.Methode2();
}
}
}
Hi,
naja - wenn all deine Zellen von CommonCell erben und gleichzeitig auch das (mir unbekannte) Interface implementieren müssen, wäre es am einfachsten, wenn deine CommonCell auch das Interface "beerbt". (In einer abstrakten Klasse muss es ja nicht implementiert werden)
Dann könntest du die foreach-Schleife so lassen. Sofern das in deinem Aufbau so möglich ist, wäre das auch die beste Lösung.
So zum Beispiel:
public interface ICell
{
void Do();
}
public abstract class CommonCell : ICell
{
public abstract void Do();
}
public class MyCell1 : CommonCell {
public override void Do()
{
throw new NotImplementedException();
}
}
public class MyCell2 : CommonCell {
public override void Do()
{
throw new NotImplementedException();
}
}
Wenn das nicht geht - dann wirst du die einzelnen Zellen "casten" müssen, dafür gibt es gleich mehrere Varianten:
Grundaufbau:
public interface ICell
{
void Do();
}
public abstract class CommonCell
{
}
public class MyCell1 : CommonCell, ICell {
public void Do()
{
// ignore
}
}
public class MyCell2 : CommonCell, ICell {
public void Do()
{
// ignore
}
}
Durchführung:
static void LoopWitCast()
{
// GetSampleData returns IEnumerable<CommonCell>
// V1: Cast all of them
foreach (var c in GetSampleData().Cast<ICell>())
{
c.Do();
}
// GetSampleData returns IEnumerable<CommonCell>
// V2: Using as
foreach (var c in GetSampleData())
{
var cell = c as ICell;
cell?.Do();
}
// GetSampleData returns IEnumerable<CommonCell>
// V3: Using direct cast
foreach (var c in GetSampleData())
{
var cell = (ICell) c;
cell.Do();
}
}
LG
Dabei sollte man noch explizit darauf hinweisen, dass eine Klasse nicht zwangsläufig alle Interface Methoden/Eigenschaften nach aussen posaunt, denn so ein Interface, bzw. die Methoden/Eigenschaften, kann/können an einer Klasse auch explizit implementiert sein.
interface IFoo
{
string GetName();
}
class Bar : IFoo
{
public string GetName()
{ return "Bar"; }
// explizite Implementierung von IFoo
string IFoo.GetName()
{ return "IFoo"; }
}
void OutputBar( Bar barArg )
{ Console.WriteLine( barArg.GetName() ); }
void OutputFoo( IFoo fooArg )
{ Console.WriteLine( fooArg.GetName() ); }
void Output( Bar barArg )
{ Console.WriteLine( barArg.GetName() ); }
void Output( IFoo fooArg )
{ Console.WriteLine( fooArg.GetName() ); }
void Main()
{
Bar bar = new Bar();
OutputBar( bar ); // Bar
// mit implizitem Cast nach IFoo
OutputFoo( bar ); // IFoo
Output( bar ); // Bar
// mit explizitem Cast nach IFoo
Output( bar as IFoo ); // IFoo
Output( (IFoo)bar ); // IFoo
}