static non-static

Hallo allerseits,

nach jahelangem "wildem Programmieren" habe ich jetzt die Gelegenheit, meine KEnntnisse in einer Fortbildung mal auf sicher Beine zu stellen.
Ich schaffe es aber nicht, das folgende Problem zu lösen:

ich habe echt lange gesucht, passendes gefunden, aber das hat mir nicht weitergeholfen (zu doof?)

Ich habe die Klasse Karten und die Klasse Stapel erstellt (Stapel extends Karte)

In Karte gibt es zum Beispiel die Methode:

12405
(Ich habe es zunächst anstatt mit this mit aktuelleKarte probiert und hatte gehofft, das sich das Problem mit this löst, hat es aber nicht.

Jetzt muss ich diese Methode aus Stapel aufrufen

12406
und dann kommt halt der berühmte Anfängerfehler "can-t make a static......

Ich habe versucht, alle MEthoden non-static zu machen, da sie das nach meinem Verständnis ja auch nicht sind (oder?!?!?!?!)
Aber irgendwie muss ich doch übergeben, welche Karte ich zeigen lassen will.

Wer kann mir weiterhelfen?

P.S.: Ich stelle mich jetzt auch in meinem Profil vor.
 
Moin,

kann man IMHO so schlecht beurteilen, da wior den relevanten Code nicht kennen!
Es kann sicher gute Gründe geben, etwas static zu machen!

Poste mal mehr Infos!

VG Klaus
 
K

kneitzel

Also in der Regel ist es so, dass Du mit Klassen beschreibst, wie Objekte aussehen und sich verhalten. Und dann sprichst Du diese Objekte gezielt an.

Also eine Klasse Karte hat dann von mir aus eine Methode zeige (Karte ist unnötig, denn Du rufst das zeige ja auch einer Karte auf), wobei hier ggf. die Methode toString überschrieben werden sollte....). Und die Karte selbst wird nicht übergeben - auf diese kannst Du dann ja per this zugreifen. Somit hätte man dann ggf. sowas:
Java:
public void zeige() {
    System.out.println("" + farbe + " " + wert);
}
Das "this." kann auch weggelassen werden - es ist klar, dass hier die Instanzvariablen angesprochen werden sollen....

Und wenn Du die Karten in einem Array speicherst in Deinem Kartenstapel, dann kann karten[0] die erste Karte sein. Die Methode kannst du da dann aufrufen per karten[0].zeige().
 
Kurzes Beispiel zum Thema:
Java:
class Foo {
    public static void staticDoSomething() {
        // hier steht Code
    }

  
public void nonStaticDoSomething() {
        // hier steht Code
    }
}

// wird folgendermaßen verwendet:

Foo.staticDoSomething(); // die statische Methode wird direkt auf der Klasse aufgerufen

Foo foo = new Foo();
foo.nonStaticDoSomething(); // die nicht statische Methode wird auf eine Instanz der Klasse aufgerufen
Im Normalfall hat man nichtstatische Methoden, die haben dann auch Zugriff auf die Daten, die intern zu der Instanz gehören.
 
UND anscheinend wichtig, war mir aber nicht klar, non-static Code ist "auf dem gleichen "Niveau" wie die Klasse
also außerhalb der geschweiften Klammern der Klasse?
Sorry, falsch gelesen
Wo muss dann der Konstruktor hin? In die geschweiften Klammern und damit

Wenn ich aus der Klasse "Stapel" den Konstruktor in der Klasse Karte für eine Karte aufrufen will, dann muss der auch non-static?
Danke
Grüße
Norman
 
Zuletzt bearbeitet:
Ich habe die Klasse Karten und die Klasse Stapel erstellt (Stapel extends Karte)
Ich kenne dein Programm zwar nicht da du mit dem Code etwas sparsam bist, aber mir kommt dein Konstrukt etwas merkwürdig vor.

Vererben kannst/solltest du, wenn du eine IST-EIN-Beziehnung herstellen kannst. Beispiel: Du hast die (abstrakte) Klasse Fluggerät. Von dieser Klasse kansnt du die Klassen Hubschrauber, Düsenjäger, Segelflugzeug ableiten:
class Hubschrauber extends Fluggerät{}
class Düsenjäger extends Fluggerät{}
class Segelflugzeug extends Fluggerät{}
Denn Hubschrauber, Düsenjäger, Segelflugzeug, sind Fluggeräte.

Frage: Ist ein Kartenstapel eine Karte?
 
Nein, ein Kartenspiel besteht aus Karten.
Meine Zugriffsyntax war falsch, daher kamen die Fehlermeldungen.
Ich habe eine ausgewählteKarte vom Stapel genommen und diese dann der Methode in Klammer übergeben. Vorangestellt habe ich versucht dem Programm zu sagen, wo er die Methode getFarbe suchen soll, nämlich in der Klasse Karte, also Karte.getFarbe(ausgwählteKarte)
anstatt
ausgewählteKarte.getFarbe.

Jetzt funktioniert es.

Allerdings frage ich mich folgendes:

Wenn ich in der Klasse (Stapel) einen neuenStapel erstellen will, dann muss ich eventuell dafür neueKarten erzeugen.
Dafür habe ich in der Klasse Karte die Methode karteInitiieren.

Ist diese jetzt static oder nicht?



12410
Jetzt könnte man meinen, du brauchst die Karten eh nur einmal, OK, aber was ist, wenn ich eine variable Anzahl Stapel erstellen will.
Muss die Methode StapelInitiieren static oder nicht sein?

12411

Danke für die Antworten!

Norman
 

Anhänge

K

kneitzel

Also die Methode KarteInitiieren erzeugt eine neue Instanz von Karte. Sowas kann sinnvoll sein, so man da ggf. noch Aktivitäten hinein packt. Aber bei Dir ist das ja nur ein einfaches new Karte() -> das macht damit also nicht wirklich Sinn, denn der Konstruktor kann ja so direkt aufgerufen werden. Wenn man so eine Builder Methode haben will, dann ist diese tatsächlich statisch.

Und wenn Dein Stapel keine Karte ist, dann ist da auch ein extends falsch. In dem Stapel sind Karten, aber der Stapel ist keine Karte. Du solltest das extends Karte ersatzlos streichen können.

Code bitte immer in den Code Tags posten. Dann können wir den als ganzes sehen und beurteilen. Generell sind die Getter in der Form aufgebaut:
Java:
public String getFarbe() {
    return farbe;
}
Also keine Karte als Parameter, nicht statisch und dann ist der Aufruf kartenInstanz.getFarbe().

So statische Funktionen findet man in einer regulären Implementation normalerweise nicht. Wenn man eine fremde Klasse erweitern muss, dann bietet Java hier aber kein Mechanismus (Andere Sprachen wie C# oder Kotlin erlauben die Erweiterung von bestehenden Klassen, aber Java halt nicht) so dass hier dann oft eine Klasse wie <Klassenname>Util oder <Klassenname>Helper mit statischen Methoden bereit stellt Also z.B. eine StringUtils Klasse die Methoden für Strings bereit stellt. Aber das nur am Rande um zu erläutern, wo man sowas teilweise sieht.

Ansonsten in deinem Code:
- In den Schleifen fehlt die Initialisierung von i und j. Also int i = 0; bzw. int j = 0.
- Farbe und Wert sind Strings, Du versuchst da aber int Werte zu setzen. So Du nur eine Zahl haben willst, dann solltest Du evtl "" + i oder so setzen.

Tipp:
Schau Dir mal Enums an. Wenn Du eine Liste von Farben haben willst, dann kannst Du ein Enum für die Farben definieren und dann ist farbe vom Typ Farbe (So dein enum Farbe heisst).
Das Gleiche dann auch für Wert.

Oder Du machst diese Werte zumindest als public, damit Du auf die Farben / Werte zugreifen kannst. Diese Konstanten werden dann aber bitte auch gross geschrieben: FARBEN, WERTE.
 
Danke, die Farben sind Teile von Arrays. Die brauche ich nur zu Beginn des Spiels um den Anfangsstapel Blatt zu erzeugen.

farbe bei get ist also in dem Sinne kein String sondern nur ein Verweis auf den Platz im Array.
bei set ist die Farbe allerdings ein STring, da an der iten STelle ja ein String seht und der in farbe gespeichert wird.
ENUMs werde ich mal betrachten.
Ja, i und j haben kein 0, nicht aufgefallen
Auf Farben muss ich nur in der KLasse Karte zurückgreifen, daher habe ich Sie private gemacht.

Wenn ich das richtig verstanden habe gibt es sowas wie Interface die man implementieren kann um Klassen zu erweitern?

Wann benutzt man super, um Klassen zu implementieren?

Ich dachte, ich muss extends Karten schreiben, weil ich ja auf die MEthoden für die Karten IN dem Stapel zugreifen will, aber das kann ich das wohl weglassen.

Danke
Norman
 
K

kneitzel

Also der Stapel muss doch die Karten erstellen. Also braucht der Stapel das Wissen zu den Farben. Daher sollte der Stapel auch darauf zugreifen können.

Du kannst natürlich die Farbe als einen index für das Array speichern. Dann sollte es aber generell ein int sein und String.

Die Lösung mit den Enums würde ich Dir aber ans Herz legen. Das scheint mir hier erst einmal die beste Lösung zu sein.

Dann hättest Du zwei enums für Farbe und Wert.
Und der Stapel kann dann alle Karten anlegen mit for each schleifen also mit sowas wie:
Code:
for(Farbe farbe: Farbe.values()) {
  for (Wert wert: Wert,values()) {
    add(new Karte(farbe, wert));
  }
}
Damit dieser Code so funktioniert brauchst Du aber nicht nur die Enums Farbe und Wert sondern auch noch:
- im Stapel eine Methode add(Karte), um Karten hinzufügen zu können.
- Karte benötigt einen Konstruktor, der Farbe und Wert entgegen nehmen kann.

Zu dem existierenden Code noch paar Hinweise:
- Bei der Erstellung zählst du die variable k scheinbar nicht hoch. Somit wird immer die erste Karte gesetzt.
- Ich würde beim Stapel einen Konstruktor erwarten, der Anzahl und das Karten Array von Hand setzt. Die Anzahl ergibt sich doch über Anzahl der Farben und werte und das Array muss erst einmal leer erzeugt werden...
Oder man hat einen Parameter, der die Anzahl der verwendeten Kartensets entgegen nimmt. Also wenn man z.B. mit 2 Kartenspielen gleichzeitig spielen möchte oder so ...
 
Ein Interface erweitert eine Klasse um eine Funktionalität.

Beispiel: Ich hatte oben die Klassen Hubschrauber, Düsenjäger und Segelflugzeug erwähnt, die alle von der abstrakten Klasse Fluggerät abgeleitet werden. Jetzt implementieren wir ein Interface 'Schwimmfähig' in einer abgeleiteten Klasse:
Java:
public interface Schwimmfähig{
    public void schwimmen();
}
Damit könnte man jetzt z.B. ein Wasserflugzeug bauen:
Java:
public class Wasserflugzeug extends Fluggerät implements Schwimmfähig{
    public void schwimmen(){
        //Klassenabhängige Implementierung
    }
}

Wann benutzt man super, um Klassen zu implementieren?
Gar nicht. Mit 'super' wird auf eine Methode der Superklasse zugegriffen.
 
Ich habe immernoch das Problem mit static usw.

Ich habe die Initiierungsmethoden rausgeschmissen.
ABER, das hilft auch nicht weiter.
Wenn ich das Gesamtblatt erstelle, beschwert der Compiler sich immer, das setFArbe usw nicht statisch ist.

Ich finde keine Lösung!

Danke für Eure Hilfe!

Norman

Java:
import java.util.Random;

public class Stapel {
    
    private int anzahl;
    private  Karte [] karten;
    
    public void Stapel (int anzahl, Karte [] karten ) {
        this.anzahl = anzahl;
        this.karten= karten;
    }
    
        
    public static Stapel BlattErstellen( ) {
        Stapel Blatt = new Stapel();
        int k = 0;
        for (int i =0; i<4; i++) {
            for (int j=0; j < 8; j++) {
                karten[k] = new Karte;
                karten[k].setKontrollnummer (k);
                karten[k].setFarbe (i);
                karten[k].setWert(j);
            }
        }
        return Blatt;
    }
    
    public   Stapel StapelErstellen (int anzahl) {
        Stapel stapel = new Stapel();
        stapel.anzahl = anzahl;
        
        
        
        
        return stapel;
        
    }
            
    public void Mischen () {
        Karte zwischenSpeicher;
        Karte tauschPartner;
        int zufallsZahl;
        Random random = new Random();
        for (int i=0; i<anzahl-1;i++) {
            zufallsZahl= random.nextInt(anzahl);
            zwischenSpeicher = karten [i];
            karten [i]= karten [zufallsZahl];
            karten [zufallsZahl]=tauschPartner ;
        }
        
        
    }
    
    
    public int getAnzahl () {
        return anzahl;
    }
    
    public Karte holeErsteKarte () {
        return karten[anzahl-1];
    }
    
    public void zeigeErsteKarte () {
        karten[anzahl-1].zeigen();
    }
    
    
    public void zeigeKarten () {
        for (int i =0; i<= anzahl-1; i++) {
            System.out.print("Karte :  " +i);
            karten[i].zeigen();
        }
    }
    
    public Karte  getObersteKarte () {
        Karte obersteKarte= karten[(anzahl-1)];
        karten[anzahl-1] = null;
        anzahl = anzahl-1;
        return obersteKarte;
    }
    
    public Karte  KarteAnPositionNehmen (int p) {
        Karte gewählteKarte= karten[p];
        for (int i = p; i<(anzahl-1);i++) {
            karten [i]=karten[i+1];
        }
        karten[anzahl-1] = null;
        anzahl = anzahl-1;
        return gewählteKarte;
    }
    
    public void KarteHinzufügen (Karte karte) {
        karten[anzahl]=karte;
        anzahl= anzahl+1;
    }
    
    
    
}
 
Ihr habe natürlcih recht.

Einen normalen Stapel erzeuge ich auch anders. Indem ich vom gemischten Blatt die entsprechende Anzahl Karten ziehe.

Mit den Farben, das kann man sicher besser lösen.

Allerdings haben mir eure Antworten leider nicht zu static non-static weitergeholfen.

Wo stehe ich hier auf dem Schlauch?

Danke
Grüße
Norman
 
K

kneitzel

Also derzeit frage ich mich, wie Dein Code überhaupt ansatzweise compilieren soll....

Deine Klasse Stapel hat einen Konstruktor, der zwei Parameter verlangt. Aber Du rufst immer einen Konstruktor ohne Parameter auf.

Dann bei dem Erstellen der Karte hast du nur "new Karte" statt "new Karte()" - es fehlen also die Klammern.

Solche Fehler würde ich erst einmal beseitigen. Ansonsten sehen die Aufrufe des Setters korrekt aus, die da nach der Zeile mit dem new kommen.

Vorschlag:
Gib einmal alle Deine aktuellen Klassen komplett und dann nehmen wir diese Fehler einmal raus, damit es kompiliert. Denn im Augenblick fürchte ich, dass Dich andere Probleme daran hindern, womöglich Richtiges als richtig zu erkennen.
 
Eigentlich ganz einfach. Bei dem was du vorhast sollte nirgendwo ein static auftauchen, mal abgesehen von der public static void main Methode. Also raus mit allen statics, du wirst danach auf viele andere Fehler treffen, aber du bist dann schon mal ein Stück weiter.
 
OK!

Dann mache ich das. Aber ich habe das Problem bei laufenden Projekten auch gehabt, und da habe ich unwissend einfach alles auf static gesetzt, damit es funktioniert.

Also erstmal fertig machen.

Poste ich dann auch alle Klassen?

Grüße
Norman
 
K

kneitzel

Nicht alles fertig machen sondern erst einmal offensichtliche Fehler korrigieren, so dass es compiliert werden kann.

==> Code sollte meiner Meinung nach immer nur für möglichst kleine Zeitfenster nicht übersetzbar (und nicht testbar, aber mit Unit-Tests hast Du derzeit wohl noch nichts am Hut) sein.

Daher sollte man jetzt als erstes dafür sorgen, dass der Code übersetz werden kann. (Und das nicht durch unnötiges Einfügen von static!)

Daher wäre meine Bitte, den aktuellen Stand einmal zu teilen. Und das sind mind. die Klassen Karte und Stapel, aber evtl. auch noch etwas drumherum (falls Du z.B, eine Klasse mit main Methode hast oder Du schon eine enum angelegt hast oder so, dann sollten die auch mit kopiert werden).

Und die Hilfe, die ich angeboten habe, ist, dass ich (oder wir) dann zusehen, dass wir den aktuellen Stand etwas überarbeiten, so dass Du dann mit einem compilierbaren Stand etwas weiter machen kannst.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben