Benutzer mit den meisten Antworten
Verschiedende Eigenschaften der selben Klasse

Frage
-
Hallo,
Ich bin noch ziehmlicher Anfänger und habe da ein Problem mit "Klassen"
Zum Sachverhalt:
Ich habe mir eine Klasse Namens "Fahrzeug" angelegt und dieser die Eigenschaften Name,Länge, Breite , Höhe , LeerGewicht und Zuladung angelegt.
Nun habe ich ein Objekt der Klasse instanziert und dieser dann die Eigenschaften eines LKW's zu gewiesen und diese Fahrzeuge in einer Liste
(Fahrzeugpark as new List(of Fahrzeug) gelegt.
So habe ich mir dann ein ganzen Fuhrpark von Fahrzeugen zu gelegt.
Nun zu meinem Problem.
Sagen wir mal ich benötige zwei mal den selben Lkw für eine bestimmte Berechnung und diese dann in einer Zweite Liste packen dann würde ich das so machen (nur als Beispiel) :
Dim Transportkolone as new List(of Fahrzeug)
Transportkolone.add(Fuhrpark.Item(2))
und das zweite (selbe Fahrzeug)
Transportkolone.add(Fuhrpark.Item(2))
nun habe ich aber das Problem wenn ich bei Fahrzeug 1 (Transportkolone.item(0).Beladung = 500) 500 Kg Gewicht "einlade dann macht er das Auch bei Fahrzeug 2
Ich habe auch probiert :
Dim i as new Fahrzeug ( Dacht mir einfach eine Neue Instanz von Fahrzeug schaffen)
i = Fuhrpark.item(0)
Transportkolone.add(i)
geht aber auch nicht
Immer das Gleiche: Ändere ich eine Eigenschaft
dann ändern sich alle des selben Fahrzeugs
Wie kann ich da Abhilfe schaffen?
Vielen Dank für die Hilfe
Antworten
-
Hallo Daniel,
ob LKW, Waggons oder Flugzeuge ist dabei vollkommen egal ;-)
Zu ByRef und ByVal:
Das hängt zwar teilweise zusammen ist aber nicht identisch.
Das .NET Framework unterscheidet zum einen zwei grundlegende Typen,
Referenz- bzw. Verweistypen (Class in Visual Basic) und Wertetypen (Structure).
http://msdn.microsoft.com/de-de/library/t63sy5hs.aspx
und in 99 Prozent der Fälle wirst man Class verwenden.
Das die Schlüsselwörter ByVal bzw. ByRef bei Parametern wiederum
geben an, wie der Wert übergeben wird:
Übergeben von Argumenten als Wert und als Verweis
und auch hier wird man in den meisten Fällen ByVal verwenden,
um eine unbeabsichtige Veränderung zu verhinden. Und das wird
von Visual Basic deswegen als Vorgabe eingesetzt.
Und ByRef setzt man selten und kontolliert nur da, wenn es wirklich beabsichtigt ist.
Zu 1.)
Du mußt alle Werte übertragen, die das neue Objekt übernehmen soll.
Nach Deinem Codeschnippsel sind das einige mehr, als in meinem kurz gehaltenen Beispiel.
Und Du kannst den Code, den Du bereits hast in den Konstruktor übertragen.
Und damit existiert der Code nur einmalig.
Zu 2.)
Die IClonable Schnittstelle wird an einigen Stellen im .NET Framework genutzt - Pflicht ist sie nicht.
Da sie für die allgemeine Anwendung zu unbequem ist, denn man müsste schreiben
DirectCast(i.Clone(), Fahrzeug)
habe ich sie nur als explizite Schnittstelle definiert, die die typisierte (As Fahrzeug) aufruft.
Zu ToString()
Jede .NET Klasse erbt Object.ToString .
Wobei die dortige Omplementation nur den Klassennamen ausgibt.
Für eigene Klassen kann man sie nutzen, um die Inhalte (alle oder die wichtigsten) auszugeben.
Das ist wie im Beispiel zum einen hilfreich, um sich die Inhalte im Programm ausgeben zu lassen.
Die integrierten Typen insbesondere die Standardtypen unterstützen noch mehr:
Formatierung von Typen
Was für Deine Waggons aber weniger in Frage kommt.
Gruß Elmar
- Als Antwort markiert B00NE Donnerstag, 20. August 2009 11:46
Alle Antworten
-
Hallo,
wenn Du eine Instanz einer Klasse einer anderen Liste (oder jeder anderen Variable) zuweist,
so wird nur die Referenz der Variable übertragen. Die Inhalte verändert sich nicht.
Um eine Kopie einer Instanz zu erstellen, verwendet man idR. einen sog. Copy-Konstrutor,
der eine neue Instanz erstellt und alle Eigenschaften der Klasse kopiert.
.NET sieht dafür auch die IClonable Schnittstelle vor, die leider den Nachteil hat, nicht strengtypisiert zu sein.
Damit es einfacher ist, bietet sich eine zusätzliche typisierte Variante an.
Für eine reduzierte Variante Deiner Klasse könnte das dann wie folgt aussehen:
Public Class Fahrzeug Implements ICloneable Public Sub New() End Sub Public Sub New(ByVal fahrzeug As Fahrzeug) Me._name = fahrzeug._name Me._zuladung = fahrzeug._zuladung End Sub Private _name As String Public Property Name() As String Get Return If(Me._name, "Ohne Namen") End Get Set(ByVal value As String) Me._name = value End Set End Property Private _zuladung As Double Public Property Zuladung() As Double Get Return Me._zuladung End Get Set(ByVal value As Double) Me._zuladung = value End Set End Property Public Function Clone() As Fahrzeug Return New Fahrzeug(Me) End Function Private Function ICloneableClone() As Object Implements System.ICloneable.Clone Return Me.Clone() End Function Public Overrides Function ToString() As String Return String.Format(Nothing, _ "[Fahrzeug: Name: {0}, Zuladung: {1}", _ Me.Name, Me.Zuladung) End Function End Class
Und etwas Beispielcode wie man damit arbeitet:
Public Shared Sub TestFahrzeug() Dim Fuhrpark As New List(Of Fahrzeug) Dim f As New Fahrzeug() With {.Name = "HH EK 247", .Zuladung = 300} Fuhrpark.Add(f) ' oder kürzer Fuhrpark.Add(New Fahrzeug() With {.Name = "HF XY 134", .Zuladung = 1300}) For Each f In Fuhrpark Console.WriteLine("Fuhrpark: {0}", f) Next Dim kolonne As New List(Of Fahrzeug) ' Kopie des ersten Fahrzeugs anlegen kolonne.Add(Fuhrpark(0).Clone()) kolonne(0).Zuladung = 100 ' Suchen über eine Funktion f = Fuhrpark.Find(Function(suche) (suche.Name = "HF XY 134")).Clone() f.Name = "HF ZZ 4711" kolonne.Add(f) For Each f In kolonne Console.WriteLine("Kolonnenfahrzeug: {0}", f) Next End Sub
Gruß Elmar
-
Dank dir Elma !
Das mit dem byRef/byVal habe ich mir schon fast gedacht aber konnte mit meinem beschränkten wissen nicht zu einer Lösung kommen.
Ich hate mich Gestern Nachmittag auch nochmal ran gesetzt und folgende Lösung gefunden die aber wie ich zugebe bei weiten nicht so
Professionell gelöst wurde wie deine. (...und wie ihr seht handelt es sich in meinen Program nicht um LKW's sondern Eisenbahnwagons :-) )
Dim Der_Zug as new List (of Fahrzeug) Dim i As New Fahrzeug Dim ii As Fahrzeug = cboWagen.SelectedItem i.Achsen = ii.Achsen i.Art = ii.Art i.Bildpfad = ii.Bildpfad i.Bremsstellungleer = ii.Bremsstellungleer i.BrH = ii.BrH i.BrLeer = ii.BrLeer i.BrVoll = ii.BrVoll i.Kupplung = ii.Kupplung i.LadungsArt = ii.LadungsArt i.LüP = ii.LüP i.Masse = ii.Masse i.MaxMasse = ii.MaxMasse i.Name = ii.Name i.Ps = ii.Ps i.Streckenklasse = ii.Streckenklasse i.Vmax = ii.Vmax Der_Zug.Add(i)
Ich hab einfach Zwei Instanzen erstellt und jeden Einzelnen Member dem anderen Zugewiesen.
ich werde aber deine Variante verwenden ( da 1. Deine Variante weitaus professioneller gelöst wurden und 2. Ich es ja gleich richtig lernen will.)
Also kann man Zusammenfassend sagen das ich in meiner Klasse nur:
1. ein neuen Konstruktor einfügen muß der ein neues Fahrzeug erstellt ( byValue)
in denen dann alle Member der neuen Fahrzeugklasse übergeben werden.
Public Sub New(ByVal fahrzeug As Fahrzeug) Me._name = fahrzeug._name Me._zuladung = fahrzeug._zuladung End Sub
2. eine Methonde Names Clone erstellen erstellen die dieses Neu Fahrzeug zurück gibt.
Public Function Clone() As Fahrzeug Return New Fahrzeug(Me) End Function
So und nun wird es Interessant :
Wie wird den die folgende Function aufgerufen ?
Private Function ICloneableClone() As Object Implements System.ICloneable.Clone Return Me.Clone() End Function
Und wo zu dient diese Function?
Public Overrides Function ToString() As String Return String.Format(Nothing, _ "[Fahrzeug: Name: {0}, Zuladung: {1}", _ Me.Name, Me.Zuladung) End Function
Vielen Dank nochmals für die Hilfe
Daniel- Bearbeitet B00NE Donnerstag, 20. August 2009 10:18
-
Hallo Daniel,
ob LKW, Waggons oder Flugzeuge ist dabei vollkommen egal ;-)
Zu ByRef und ByVal:
Das hängt zwar teilweise zusammen ist aber nicht identisch.
Das .NET Framework unterscheidet zum einen zwei grundlegende Typen,
Referenz- bzw. Verweistypen (Class in Visual Basic) und Wertetypen (Structure).
http://msdn.microsoft.com/de-de/library/t63sy5hs.aspx
und in 99 Prozent der Fälle wirst man Class verwenden.
Das die Schlüsselwörter ByVal bzw. ByRef bei Parametern wiederum
geben an, wie der Wert übergeben wird:
Übergeben von Argumenten als Wert und als Verweis
und auch hier wird man in den meisten Fällen ByVal verwenden,
um eine unbeabsichtige Veränderung zu verhinden. Und das wird
von Visual Basic deswegen als Vorgabe eingesetzt.
Und ByRef setzt man selten und kontolliert nur da, wenn es wirklich beabsichtigt ist.
Zu 1.)
Du mußt alle Werte übertragen, die das neue Objekt übernehmen soll.
Nach Deinem Codeschnippsel sind das einige mehr, als in meinem kurz gehaltenen Beispiel.
Und Du kannst den Code, den Du bereits hast in den Konstruktor übertragen.
Und damit existiert der Code nur einmalig.
Zu 2.)
Die IClonable Schnittstelle wird an einigen Stellen im .NET Framework genutzt - Pflicht ist sie nicht.
Da sie für die allgemeine Anwendung zu unbequem ist, denn man müsste schreiben
DirectCast(i.Clone(), Fahrzeug)
habe ich sie nur als explizite Schnittstelle definiert, die die typisierte (As Fahrzeug) aufruft.
Zu ToString()
Jede .NET Klasse erbt Object.ToString .
Wobei die dortige Omplementation nur den Klassennamen ausgibt.
Für eigene Klassen kann man sie nutzen, um die Inhalte (alle oder die wichtigsten) auszugeben.
Das ist wie im Beispiel zum einen hilfreich, um sich die Inhalte im Programm ausgeben zu lassen.
Die integrierten Typen insbesondere die Standardtypen unterstützen noch mehr:
Formatierung von Typen
Was für Deine Waggons aber weniger in Frage kommt.
Gruß Elmar
- Als Antwort markiert B00NE Donnerstag, 20. August 2009 11:46