Laden...

Ansprechen von Eigenschaften und Methoden von Objekten (objektorientierte Programmierung)

Erstellt von BlauerTeddy vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.551 Views
B
BlauerTeddy Themenstarter:in
4 Beiträge seit 2019
vor 4 Jahren
Ansprechen von Eigenschaften und Methoden von Objekten (objektorientierte Programmierung)

Hallo liebe Programmierer!

Ich habe ein Problem für das ich seit Wochen in meiner Freizeit eine Lösung suche. Bitte lacht Euch nicht kaputt, wenn ihr mein Problem seht. Aber ich kapiers einfach nicht..

Ich möchte nachdem ich eine Klasse angelegt habe, Objekte davon anlegen. Soweit klappt das auch alles. Aber wenn ich die Methoden des Objekts oder seine Eigenschaften ansprechen möchte, bekomme ich nur eine Fehlermeldung.

Ich schreibe in C# mit WPF, aber ich denke nicht, dass es ein WPF-Problem ist.

namespace Objekte_und_Methoden_Test
{
    class Helden
    {
        public string name { get; set; }
        public int alter;
        public int stärke;
        public int lebensenergie;

        public void Kampf(int schaden)
        {
            lebensenergie = stärke - schaden;
        }

        public void Heilung()
        {
            lebensenergie++;
        }
    }
}

Mein eigentlicher Programmcode:

namespace Objekte_und_Methoden_Test
{

    public partial class MainWindow : Window
    {
            
        public MainWindow()
        {
            InitializeComponent();
            Helden Marco = new Helden();
            {
                Marco.alter = 20;
                Marco.name = "Marco";
                Marco.lebensenergie = 20;
                Marco.stärke = 10;
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Marco.alter++; //<--- FEHLER
        }
    }
}

Mein Problem ist, dass er "Marco.alter" nicht erkennt. Er sagt dann immer > Fehlermeldung:

"CS0103 Marco ist im aktuellen Kontext nicht vorhanden."

301 Beiträge seit 2009
vor 4 Jahren

Im Scope deine Button Click Methode die vermutlich über einen Eventhandler ausgeführt wird ist die Instanz deiner Klasse Helden bereits nicht mehr verfügbar.

Der Ablauf bei dir wäre:

  • MainWindow wird erstellt
  • Klasse Helden wird erstellt
  • Klasse Helden wird verworfen da sie nirgendwo zwischengehalten wird

Du kannst dir das so vorstellen, als dass am Ende jeder Methode alles weggeräumt wird was du innerhalb einer Methode gemacht hast, es sei denn du tust Dinge um deine erstellten Konstrukte irgendwo zwischen zu speichern. Gewöhnlich passiert das über instanzvariablen. Ähnlich hast du das bereits bei deiner Helden Klasse gemacht.

Natürlich ist es nicht unbedingt immer klug alles in Klassenvariablen zwischen zu halten, aber für dein momentanes Verständnis sollte dich diese Info vielleicht weiterbringen.

B
BlauerTeddy Themenstarter:in
4 Beiträge seit 2019
vor 4 Jahren

Ich glaube es dank deiner Hilfe gelöst zu haben! 😃

{
	public partial class Window1 : Window
	{
		Helden Marco = new Helden();
		Helden Tobias = new Helden();
		
		
		public Window1()
		{
			InitializeComponent();
			
			Marco.alter=40;
			Marco.name="Marco";
			Tobias.alter=38;
			Tobias.name="Tobias";
		}
						
		void button1_Click(object sender, RoutedEventArgs e)
		{
			string Ergebnis = ""+Marco.alter;
			TextBox1.Text = Ergebnis;
		}
	}
}

Es scheint als läge die Lösung darin die Objekte in der äußersten geschweiften Klammer zu erzeugen.
Die Eigenschaften dürfen dann aber erst später behandelt werden. Sonst kommts wie bei mir so oft zu Fehlermeldungen.
Allerdings dachte ich schon öfter ich hätte es gelöst. 😄

Ist das ein passender Weg? Oder bringt dieses Vorgehen später andere Probleme?

3.003 Beiträge seit 2006
vor 4 Jahren

Es scheint als läge die Lösung darin die Objekte in der äußersten geschweiften Klammer zu erzeugen.

Nein, mit der Erzeugung hat das nichts zu tun. Du hast zwei unterschiedliche Arten von Variablen erzeugt. Im ersten Versuch - der mit dem Fehler - handelt es sich um eine lokale Variable. Diese ist nur innerhalb der Methode verfügbar, in der sie deklariert, erzeugt und gefüllt wurde.

Im zweiten Versuch jetzt hast du eine sogenannte Instanzvariable (auch: "Feld") erzeugt. Deine Klasse "Window1" hat jetzt zwei Felder "Marco" und "Thomas". Diese beiden Felder sind innerhalb der Klasse überall bekannt. Du kannst sie an jeder Stelle erzeugen (mit "new"). Eine übliche Stelle wäre der Konstruktor der Klasse, eine zweite übliche Stelle wäre dort, wo du es gemacht hast (gleich bei der Deklaration).

Instanzvariablen solltest du mit Zugriffsmodifikatoren versehen. Diese regeln, der alles auf sie zugreifen darf. "private" heisst: nur innerhalb der Klasse. Bei der Namensvergabe für private Felder wird häufig ein _ dem kleingeschriebenen Namen vorangestellt. Siehe auch [Artikel] C#: Richtlinien für die Namensvergabe .


public class Window1 : Window
{
    private Helden _marco;
    private Helden _tobias = new Helden();
    private Helden _robin; //nur Deklaration ("Bekanntmachung"), kein Erzeugen ("Instanziierung")

    public Window1() 
    {
         this._marco = new Helden(); //Variante über Konstruktor. "this" kann auch weggelassen werden, es zeigt an, dass es sich um Element der Klasse handelt.
         _marco.Alter = 40;
         _marco.Name = "Marco";
         _tobias.Alter = 20;
         _robin.Alter = 24; //Fehler: Robin wurde noch nicht erzeugt!
         _robin = new Helden();
    }
}

Das sind allerdings sehr grundlegende Grundlagen in der OOP, nicht einmal spezifisch für C#, sondern so (oder fast so) auch gültig in jeder anderen objektorientierten Hochsprache.

Wäre ein guter Zeitpunkt, um mal ein Buch zur Hand zu nehmen 😃.

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)

B
BlauerTeddy Themenstarter:in
4 Beiträge seit 2019
vor 4 Jahren
Aus Klassen erzeugte Objekte zu anderen Frames mitnehmen

Hallo liebe Alle,

Die Monate vergingen und ich habe ein leider sehr essentielles Problem nicht lösen können.
Wenn ich in WPF ein Objekt erzeuge (Beipiel: das Objekt "Marco" der Klasse "Held"), so bleibt es plump gesagt in dem Frame, in dem ich es erzeuge. Das nächste Frame, das ich in eine Form lade weiss nichts von dem Objekt. Natürlich kann ich Werte mit dem Konstruktor übergeben, doch eben keine Objekte. und bei über 150 Variablen (wenn ich Klassen und Objekte umgehe) ist das echt mühsam und komplex.
Ich bat einen C++ Programmierer um Hilfe. Allerdings stieß er recht überrascht auf das gleiche Problem.
Ich bitte Euch abermals um Rat, wie ich nicht nur Variablen, sondern ganze Objekte von einem Frame zu dem nächsten übergeben kann.

In den Büchern "Einstieg in C# für mit Visual Studio 2019" und "Windows Presenter Foundation", sowie der Videoreihe C# Masterkurs aus programmieren-starten.de. Fand ich keine Behandlung meines Problems.

Zur Zeit arbeite ich wieder in Umgehung der Objektorientierung nur mit vielen Variablen ohne Klassen und Objekte dafür anzulegen.

Ich wäre Euch WIRKLICH dankbar, wenn ihr mir da einen Hinweis auf mein fehlerhaftes Verständnis geben würdet. Wo denke ich so falsch, dass in keinem Buch oder so auch nur Jemand an so ein Problem denken braucht?

5.657 Beiträge seit 2006
vor 4 Jahren

Das Stichwort ist doch bereits in den vorherigen Antworten gegeben worden: Scope bzw. Gültigkeitsbereich von Variablen.

Der Rest ist Objektorientierte Programmierung. Masterkurse und Bücher zu WPF behandeln das sicherlich nicht, sondern setzen es voraus.

Fang lieber erstmal damit an, dir eine Objektstruktur zu überlegen, und wenn das grundsätzlich funktioniert, kannst du mit WPF loslegen. Scheint, als hättest du dich da ein wenig übernommen.

Weeks of programming can save you hours of planning

T
461 Beiträge seit 2013
vor 4 Jahren

Um es noch spezifischer zu beantworten, wäre etwas Code nicht schlecht, um sich generell ein Bild machen zu können.

Vielleicht fehlt ihm ja nur ein kleiner Stupser zu dem großen Ahaaaa 😉

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

J
251 Beiträge seit 2012
vor 4 Jahren

Natürlich kann ich Werte mit dem Konstruktor übergeben, doch eben keine Objekte.

Hast du denn schon mal versucht einen Konstruktor zu erstellen, welcher in der Signatur ein Objekt vom Typ "Helden" bzw. mehrere Objekte vom Typ z.B. List<Helden> möchte?

B
BlauerTeddy Themenstarter:in
4 Beiträge seit 2019
vor 4 Jahren

Ich habe aktuell das Problem, dass ich in WPF keine klassische Main-Methode habe.
Vielmehr wird die MainMethode vom System laufend neu zurück gesetzt und lässt sich auf normalem Weg nicht manipulieren.
Das zwingt mich dazu, Objekte (Instanzen einer Klasse) in den C#-Codes der Fenster und Frames des WPF anzulegen. Allerdings nimmt er mir die Objekte und auch einfache Variablen nicht mit zu den anderen Fenstern und Frames, da diese jeweils eigene C#-Codes haben. Lediglich mit dem Konstruktor kann ich diese übergeben.

Bisher habe ich folgende "Umgehungen" überlegt.

  1. Ich lasse alles in einem Fenster ohne Frames laufen. Dort kann ich die Objekte erzeugen und problemlos im gesamten Code darauf zugreifen. Dafür muss ich aber alle Buttons, Images usw. in einem Fenster erzeugen und auf Width = 0 setzen, wenn ich sie ausblenden will. Will ich sie anzeigen oder ausblenden, dann manipuliere ich mittels C#-Code diese Breite und zeige sie je nach Position im Spiel an. Das ist natürlich recht unübersichtlich in der Programmierung und Gestaltung mit all den Buttons usw. Aber.. Ich kann objektorientiert programmieren.
  2. Ich arbeite mit einem Fenster und vielen Frames. Hier kann ich je nach Position im Spiel die ensprechend gestalteten Frames ins Fenster laden. Aber.. es stirbt damit die objektorientierte Programmierung, da ich alles mittels Konstruktor übergeben muss und der mir keine Objekte nimmt. Eventuell habe ich noch nicht gecheckt, wie man Objekte über diesen überträgt. Also übergebe ich hunderte Variablen mit dem Konstrukor in das nächste Frame. Und das bei bisher etwa 10 Frames. Es ist wahnsinnig unübersichtlich und mühsam. 😦
  3. Ich lege eine Datenbank an und lese und schreiben einfach in allen Fenstern und Frames die benötigten Werte aus dieser aus oder manipuliere sie.

Mein Traum ist jedoch, dass ich in WPF über mehrere Frames hinweg die gleichen Objekte benutzen kann. So wie in einem "normalen" C#-Code.

Erzeugung des Objekts HausBaden:

namespace Laufhaus_Imperium
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Häuser HausBaden = new Häuser();
            HausBaden.Name = "Schneckenhaus";
        }

        private void HalloWeiterButton_Click(object sender, RoutedEventArgs e)
        {
            MainFrame.Content = new Startseite(); // 
        }
    }
}

In all den folgenden Frames existieren die Objekte nicht mehr. Sodass ich es aktuell mit der 2. Version versuche. Aber es scheint mir so verrückt zu sein, die objektorientierung umgehen zu müssen, um WPF mit mehreren Frames zu nutzen. Das kann nicht im Sinn der Sache sein. (ich schreibe das Spiel ja um zu lernen. Auf eine grafische Oberfläche mag ich jedoch nicht verzichten..)

Leider habe ich keine Ahnung wie die vorgeschlagene Variante mit dem Konstrukor aussehen könnte. Dafür bin ich wohl noch nicht weit genug. You-Tube-Videos zur Übergabe von Werten in WPF finde ich auch nur für einfache Variablen.

W
955 Beiträge seit 2010
vor 4 Jahren

Es wäre sinnvoll diese Anwendung mit dem MVVM-Pattern zu erstellen. Damit kannst du dir deinen Traum erfüllen: verschiedene Views (von dir Frames genannt) werden von ViewModels repräsentiert welche sich ein Model teilen (das die verschiedenen VM anzeigen sollen). Such mal nach MVVM - da gibt es sicherlich viel Literatur darüber.
Klassen sollten übrigens im Singular benannt werden, du sagst ja auch nicht "ich baue mir mal ein Häuser".


var hausBaden = new Haus { Name= "Schneckenhaus" };