Autor Beitrag
JanR
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 20.04.10 20:37 
Guten Tag,

erstmal Hallo an euch alle dies ist mein erster Post. Ich habe da ein Problem welches mich schon länger beschäftigt.

Ich habe z.B. eine Basisklasse Base die einige Variablen und Methoden beinhaltet. Von dieser Basisklasse Erben die beiden Klassen BaseXXX und BaseYYY. In BaseXXX habe ich eine Variable TestXXX und in BaseYYY habe ich die Variable TestYYY die beide nicht in der Basisklasse vorhanden sind.

Jetzt möchte ich die geerbten Klassen gerne in einer anderen Klasse verwenden. Allerdings suche ich eine möglichkeit in eine Variable "Base ContainerVar" beide geerbten Klassen speichern zu können (nicht gleichzeitig) und Zugriff auf TestXXX oder TestYYY zu haben.

Ich möchte quasi einen Container der sowohl BaseXXX als auch BaseYYY aufnehmen kann. Das klappt zwar auch durch das casten, allerdings habe ich dann nur Zugriff auf die Variablen und Methoden der Base Klasse. Gibt es einen Weg auf die zusätzlichen Variablen der jeweiligen Kindklassen zuzugreifen?

Danke und Gruß Jan
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 20.04.10 21:41 
Zitat:
Jetzt möchte ich die geerbten Klassen gerne in einer anderen Klasse verwenden.


Ähm wenn du auf die speziellen Eigenschaften der speziellen Klassen zugreifen möchten, wieso möchtest du das von einer Klasse aus? Dein ~Problem~ in dieser Klasse sollte man doch genauso mit inheritance lösen. Also eine Ableitung dieser Klasse die mit BaseXXX umgehen kann und damit mit TextXXX umgehen kann und eine andere Ableitung die das ganze mit BaseYYY kann. Ansonsten wenn das an deinem Problem vorbei geht solltest du in deiner Frage konkreter werden.
JanR Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 20.04.10 22:16 
Damit man besser versteht was ich vorhabe erkläre ich mal was ich genau mache.

Ich Programmiere grade einen grafischen Diagramm Editor in WPF und C#. Ich verwende das MVVM Entwurfsmuster und habe ein ViewModel welches in der View in einem Tabview per Datenbindung als Diagrammoberfläche dargestellt wird. Um nun einzelne Shapes auf der Diagrammoberfläche zu Selektieren habe ich an die View ein Behavior gebunden welches ausgelöst wird sobald der Benutzer mit der Maus auf die Oberfläche klickt.
Das Behavior schaut dann in erster Linie wo sich die Maus auf der Diagrammoberfläche befindet und welches Shape sich unter der Maus befindet.
Diese Daten werden dann an das ViewModel übergeben um dort auf Benutzereingaben zu reagieren. Im Moment habe ich nur eine Art von Shape nennen wir es ShapeXXX. Für ShapeXXX existiert ein Template welches das Aussehen des Shapes definiert. Wenn der Benutzer nun so ein Shape anklickt bekommt mein ViewModel die Instanz der Klasse ShapeXXX übergeben mit seinen spezifischen Daten wie Höhe, Breite, und Position.
Im ViewModel nutze ich diese Instanz jetzt um sie mit einem Adorner zu Versehen welches dann für das Vergößern und Verkleinern des Shapes zuständig ist.

Das funktioniert auch alles sehr gut. Jetzt möchte ich allerdings gerne eine weitere Shapeart z.B. ShapeYYY hinzufügen welche wie auch das erste von BaseShape Erbt aber zusätzlich noch eine weiter Variable enthält und ein anderes Template bekommt d.h. ein anderes Aussehen. Da ich jetzt nicht alles was ich für das erste Shape im ViewModel geschrieben habe nochmal für das zweite schreiben möchte suche ich eine Möglichkeit die BaseShape Klasse im ViewModel als Variable zu deklariere und je nach dem welches Shape der Benutzer anklickt entweder ShapeXXX oder ShapeYYY hineinzupacken um damit weiter zu arbeiten.

Ich hoffe das ist soweit einigermaßen verständlich auch wenn viele Begriffe aus WPF und MVVM auftauchen.

Gruß Jan
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 20.04.10 22:31 
Erst einmal noch :welcome:

Ein schönes Konzept bisher :) . Aber user profile iconRalf Jansen hatte mit seinem allgemeinen Rat schon Recht: Warum führst du kein ShapeXXXViewModel und ShapeYYYViewModel ein, die von ShapeViewModel ableiten?
Du könntest natürlich genauso gut ein einziges VM mit einem riesigen if (element is ShapeX) ... else if ... einbauen, aber Erweiterbarkeit im Sinne der OOP ist dan natürlich nicht vorhanden.

_________________
>λ=
JanR Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 20.04.10 22:41 
Hi und schonmal vielen Dank euch allen für die schnellen Antworten. Bei meiner Recherche zum MVVM bin ich auch öfter drüber gestolpert das man das Model bzw. die einzlenen Klassen des Models nochmal in ViewModels kapseln sollte.
Allerdings komme ich doch dann irgendwann auf das selbe Problem oder habe ich grad nen Denkfehler?
Wenn ich dann für ShapeXXXViewModel nen Template habe und für ShapeYYYViewModel und ich diese Klassen dann im DiagrammViewModel zurückgeliefert bekomme dann brauche ich doch wieder eine Variable in der ich sowohl ShapeXXXViewModel als auch ShapeYYYViewModel speichern kann?
Oder kommt dann die Logik für z.B. das selectieren und belegen mit nem Adorner usw. in die einzelnen ViewModels des Models? Das würde dann ja doch dazu führen das ich für jedes ViewModel die Logik erneut anpassen muss.

P.S. Es geht mir darum das ganze so Modular wie möglich zu gestalten. So das ich ohne viel Aufwand entweder wie oben Beschrieben das Model um weiter Diagrammelemente erweitern kann oder halt ganze Diagrammarten mit anderen Model Elementen hinzufügen kann. Mit den Diagrammarten habe ich das ja quasi schon drin denn wenn ich ein neues Diagramm haben möchte dann mache ich dafür ein ViewModel und lasse es in der TabView genauso wie das andere Diagramm anzeigen. Da ich meine ObservableCollection die die einzlenen Diagramme speichert und an die Tabview gebunden ist nicht auf eine Klasse festlege sondern auf ein Interface welches jedes ViewModel interpretiert (in dem steht aber eh nix drin ist nur damit die ObservableCollection alle ViewModel Arten speichern kann) kann ich dort meine Diagramme beliebig erweitern.

Nur mit der Erweiterung meiner Diagrammelemente der einzelnen Diagramme komme ich grad nicht so recht weiter. Ich dachte erst das ich da z.B. auch ne Variable anlegen kann die aus dem Interface besteht und dort dann einfach alles rein packen kann was dieses Interface implementiert aber dann fehlen die Methoden und Variablen.

Gruß Jan
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 20.04.10 23:58 
user profile iconJanR hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich dann für ShapeXXXViewModel nen Template habe und für ShapeYYYViewModel und ich diese Klassen dann im DiagrammViewModel zurückgeliefert bekomme dann brauche ich doch wieder eine Variable in der ich sowohl ShapeXXXViewModel als auch ShapeYYYViewModel speichern kann?
Genau, im Haupt-VM brauchst du eine Liste von ShapeViewModels. Du castest nun aber eben nicht innerhalb des Haupt-VMs auf die einzelnen Ableitungen, sondern benutzt virtuelle Methoden von ShapeViewModel - Polymorhpismus, so wie er sein sollte.
Du musst also sicher nicht in jeder Ableitung von vorne beginnen, sondern nur die für diese Klasse einzigartige Logik durch Überschreiben hinzufügen (das musst du wohl so oder so irgendwo machen ;) ). Alles andere gehört in die gemeinsame Basisklasse.

Mal ein kurzes Beispiel. Auf eine Trennung von Model und VM habe ich verzichtet, außerdem fehlt natürlich noch eine Prise INotifyPropertyChanged.
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
  public class Rectangle : Shape
  {
    public float Width { get; set; }
    public float Height { get; set; }

    public override void MakeBigger()
    {
      base.MakeBigger();
    }
  }

  public class MainViewModel
  {
    public ObservableCollection<Shape> Shapes { get; private set; }

    public MainViewModel()
    {
      Shapes = new ObservableCollection<Shape> {
        new Circle { Diameter = 10 },
        new Rectangle { Width = 40, Height = 30, StrokeThickness = 5 }
      };
    }

    public void MakeBigger()
    {
      foreach (var shape in Shapes)
        shape.MakeBigger();
    }
  }

ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
    <Window.Resources>

        <DataTemplate DataType="{x:Type my:Rectangle}">
            <Rectangle StrokeThickness="{Binding StrokeThickness}"
                       Width="{Binding Width}"
                       Height="{Binding Height}"
                       Fill="Red"
                       Stroke="Black" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:Circle}">
            <Ellipse StrokeThickness="{Binding StrokeThickness}"
                       Width="{Binding Diameter}"
                       Height="{Binding Diameter}"
                     Fill="Blue"
                     Stroke="Black" />
        </DataTemplate>
    </Window.Resources>
    <ItemsControl ItemsSource="{Binding Shapes}" />

_________________
>λ=