Laden...

Vererbte Klassen zu Interface vereinigen

Erstellt von exaveal vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.930 Views
E
exaveal Themenstarter:in
96 Beiträge seit 2010
vor 13 Jahren
Vererbte Klassen zu Interface vereinigen

Moin Leute.

Ich habe zwei Klassen:


class ControlA : UserControl
class ControlB : UserControl

Diese beiden Klasse haben viele gleiche Methoden, wie getLaenge(); und getWeite();
Ich möchte in einer gemeinsamen Liste List<T> diese Klassen verwalten. Dazu erstelle ich ein Interface:


public interface IInterface

und ändere die Klassen ab:


class ControlA : UserControl, IInterface
class ControlB : UserControl, IInterface

Nun erstelle ich meine Liste:


private List<IInterface> Liste = new List<IInterface>();

Nun kann ich aber über die Liste nur Methoden des Interface aufrufen:


Liste.ElementAt(0)).getLaenge();

aber leider keine Methoden der BasisKlasse UserForm. Mache ich die Liste vom Objekttyp UserForm dreht sich das Problem nur um.

Gibt es da eine Lösung? Ahhhh

E
exaveal Themenstarter:in
96 Beiträge seit 2010
vor 13 Jahren

Okay, ich könnte das Interface einfach durch eine Klasse ersetzen. Diese erbt dann von UserForm und die ControlA und ControlB erben dann von der Klasse 'Interface'.

Gibt es vielleicht eine schönere Variante?
Ich arbeite mich grad in C# ein und wollte eigentlich den Sinn von Interfaces verstehen 😄 Jetzt macht mir das Interface natürlich ziemliche Probleme weil es ja nicht die Methoden von UserControl erben kann. Knifflig knifflig ...

1.002 Beiträge seit 2007
vor 13 Jahren

Hallo exaveal,

warum erstellst du nicht eine Klasse MyControl, die von UserControl erbt und die gemeinsamen Methoden (bzw. Properties) von ControlA und ControlB enthält? ControlA und ControlB erben ihrerseits von MyControl.

Ein kleiner Hinweis zu Namenskonventionen und Verwendung von Methoden am Rande: getLaenge() und getWeite() sollten besser als Properties Width und Length angelegt werden. Sollen diese aus irgendeinem Grund trotzdem als Methode implementiert werden, würden sie GetWeite() und GetLaenge() bzw. besser GetWidth() und GetLength() genannt werden.

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

139 Beiträge seit 2010
vor 13 Jahren

Wenn deine Klasse das Interface IInterface zugewiesen hat, welches wiefolgt aufgebaut wäre:

public interface IInterface
{
   void myMethod();
}

Dann müsstest du zwingend in der Klasse diese Funktion auch anlegen, mittels:

public void myMethod()
{

}

Und somit ist sie auch im

private List<myClass> _liste = new List<myClass>();
_liste.ElementAt(0)).myMethod();

vorhanden. Ausschlagebender Punkt ist, dass die Methode public ist.

Gruss,
reloop

Zusammengefasst:

    public class myClass : UserControl , IInterface
    {
        public void myMethod()
        {

        }
    }

    public interface IInterface
    {
        void myMethod();
    }

    public class myTestClass
    {
        private List<myClass> _liste= new List<myClass>();

        public myTestClass()
        {
            _liste.ElementAt(0).myMethod();
        }
    }
E
exaveal Themenstarter:in
96 Beiträge seit 2010
vor 13 Jahren

warum erstellst du nicht eine Klasse MyControl, die von UserControl erbt und die gemeinsamen Methoden (bzw. Properties) von ControlA und ControlB enthält? ControlA und ControlB erben ihrerseits von MyControl.

Okay, ich habe das jetzt so realisiert:


    public class MyUserControl: UserControl  //ehemals IInterface
    {
        public virtual void createMenu()
        {}
        public virtual void createStatus()
        {}
    }


    public partial class ControlA: MyUserControl
    {
        public new void createMenu()
        {}
        public new void createStatus()
        {}
        public void moreMethods()
        {}
    }

Jetzt motzt aber der Compiler:
Inkonsistenter Zugriff: Basisklasse "MyUserControl" ist weniger zugreifbar als Klasse "ControlA"

urgs, wie bekomm ich denn das jetzt weg? bzw was heißt weniger zugreifbar?

//EDIT:
da war ich mal wieder zu voreilig 😃 Habe die Klasse MyUserControl inkl. Methoden als abstract deklariert und die Methoden in den Klassen ControlA/B mit override implementiert.

Danke für die schnelle Hilfe!

1.552 Beiträge seit 2010
vor 13 Jahren

Hallo exaveal,

weniger zugreifbar heißt in dem Moment dass eine Klasse Internal ist und die abgeleitete Public, in deinem geposteten Beispiel ist dies jedoch nicht der Fall. Bist du dir sicher dass das Gepostete Beispiel mit dem realen in deinem Programm der Fall ist, denn dein Beispiel kompiliert erwartungsgemäß bei mir.

Jedoch habe ich an dich eine Frage:
Haben deine Methoden in deiner **Basisklasse **einen Body? Oder sind diese nur der Zusammenfassung herausgeschnitten worden?

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

1.002 Beiträge seit 2007
vor 13 Jahren

Hallo exaveal,

schön, dass es jetzt geklappt hat – nur frage ich mich, ob deine hier gepostete Lösung deiner existierenden entspricht? (Die Fehlermeldung des Compilers rührt daher, dass MyControl einen restriktiveren Zugriffsmodifizierer hat als ControlA.
Kann es sein, dass deine Klasse MyControl folgendermaßen implizit den Modifizierer internal verwendet? Wenn ja, setze diesen explizit auf public.

class MyControl
{
    /* ... */
}

Ohne dich nötigen zu wollen, möchte ich dir nochmal die Microsoft-Namenskonventionen, speziell die Konventionen für Methoden, ans Herz legen. Diese sind weit verbreitet und sollten IMHO befolgt werden.){gray}

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

E
exaveal Themenstarter:in
96 Beiträge seit 2010
vor 13 Jahren

Hallo Leute.
Erstmal: Ich finds echt super, dass Ihr so hilfsbereit seid 😃

Also ich habe die Klassen im Startthread nur übersichtshalber gekürzt. Und das Beispiel was ich hier gepostet habe, entspricht nicht genau dem, welches ich verwende. Das hat den einfachen Grund, dass ich (so doof wies auch klingt) in meiner Bachelorarbeit für eine Firma programmiere. Ich will nur einfach nicht, dass sie durch googeln ihre Klassen in Foren wieder finden und ich am Ende wegen sowas abgemahnt werde.

Es war natürlich die internal/public Geschichte xxMUROxx. Ich habe den Code im Thread zwar richtig angepasst, allerdings das public in meiner abstrakten Klasse im Programmcode vergessen 😃

Die Namenskonventionen werde ich mir auch nochmal anschauen. Ich erschlage mich nur gerade mit ~10 Büchern und lese viel parallel.

Das Programm ist jetzt lauffähig mit der neuen abstrakten Kasse als Interface. Dafür kann ich jetzt nicht mehr den Designer in VisualStudio 2010 für die UserControls ControlA & ControlB aufrufen. Herrlich ...
Die Fehlermeldung lautet
**Der Designer kann keine Instanz des Typs TGV.TabContent erstellen, da dieser als abstrakt deklariert ist. **

Naja, dann muss ich wohl zum bearbeiten der Klasse die Ableitung entfernen und zum kompilieren wieder einfügen. Etwas umständlich, aber wenigstens gehts erstmal.