Grundsätzliche Fragen zu OOP

melmager

Erfahrenes Mitglied
Ich Quäle mich ja schon eine Weile mit Java rum aber das OOP Prinzip habe ich scheinbar immer noch nicht wirklich verstanden :-(

In meinem aktuellen - scheinbar ewigen Projekt - will ich den derzeitigen Internen Aufbau verändern - frage mich aber ob da immer noch Denkfehler sind:

class main
die erstellt dann eine Instanz von
class DatenVerwalten - class DatenAnzeigen - class DatenEdit

alle drei classen sollen die class Daten kennen und nutzen - diese class wird als datenspeicher gebraucht und verschwindet auf einer list - klar verwaltet durch DatenVerwalten.

mache ich die class Daten als inner class von Datenverwalten oder lieber eine eigene unabhängige classe ?
und wie aufwändig würdet Ihr die Methoden der class Daten machen ? - mein derzeitiger Ansatz währe ja keine Mehoden, sondern nur Variablen, da das ja nur ein Speicher ist - und ich denke mir das jede Methode einfach Platz wegnimmt wenn ich z.B. 100 mal die classe Daten auf der List habe.

Für die Variante inner class der Daten spricht - meiner Meinung nach - das dort auch Methoden untergebracht werden die für eine Umwandlung sorgen wenn die Daten von extern kommen - Eingabe / File - und von dort als Texteingabe ankommen - müssen also aufbereitet werden.

die Übergabe von Daten von einer class zur andren müsste dann ja über main realisiert werden - DatenAnzeigen würde also über Main Daten anfordern müssen die dann bei Datenverwalten ja gelagert sind

oder ist der Ansatz auch völlig daneben ?
übrigends sind alle classen nicht grade trivial aufgebaut - aber hier gehts ja nur ums OOP Prinzip - und da tauch bei komplexen Aufgaben immer die Frage auf wie trenne ich das sinnvoll ?

und Gewissensfrage Class Daten - eigene class oder inner ; mit oder ohne eigene Fuctionen ?
 
Zuletzt bearbeitet:
Also eines vorab. Wenn Du bei dieser Problemdarstellung eine ordentliche Antwort haben möchtest, solltest Du mindestens ein bißchen aufklärenden Quellcode zeigen.
Denn die meisten Programmierer spielen nach Noten, nicht nach Worten.

Also wie ich das ganze jetzt verstanden habe, handelt es sich um eine Attribut-Angelegenheit der Methoden, wie beispielsweise "public, static, protected oder private".

Aber ich unterstütze auch den Vorposter... Was muss denn die Applikation machen bzw. können?

LG
BL
 
Also ohne dich gleich entmutigen zu wollen. Du hast schonmal zu viele Klassen.

Erstmal Grundlagen:
(wenn du die schon kennst, überlies dies, aber vlt suchst du gerade das hier.)

Deine Klasse "Daten" hat höchstwahrscheinlich einen völlig falschen Namen.
Du musst dich fragen: Was sind das für Daten? Eine Adresse? Dann nenne die Klasse Adresse. Ein Auto inkl. Fahrgestellnummer, Lackfarbe und PS-Zahl? Dann nenne die Klasse Auto.
Sollte es sich um Daten im Sinne einer Datei handeln, dann nenne die Klase vielleicht besser Datei. Oder aber benutze die Java-Klasse File, die existiert extra dafür schon und bietet dir Später gute Möglichkeiten zur Weiterverwertung. Die Mehrzahl benutzt man bei Klassenname eigentlich nur, wenn in der Klasse auch mehrere Exemplare enthalten sind (z.B. Bounds - Grenzen / Schranken). Davon gibt es ja z. B. in der 2-dimensionalen Welt direkt 4.

Klassen bilden also immer irgendwas ab. Wenn du mehrere Menschen / Autos oder so hast, dann erstellst du eine Instanz einer Klasse. Also ich bin eine Instanz (oder auch Objekt) der Klasse Mensch, genau wie du. Wir haben wahrscheinlich unterschiedliche Augenfarben und so, aber wir haben beide Augenfarben, Ein Auto hat keine Augenfarben, also Klasse Auto. Ein Klasse gibt als vor welche Merkmale eine Instanz (oder Objekt) hat,

So und nun willst du deine Klasse verwalten, anzeigen und ändern.
Ändern tust du generell über sogenannte Getter und Setter-Methoden.
Bei Auto also z. B.
Java:
public void setLackFarbe(String color) {
    lackFarbe = color;
}

Mehr machen diese Funktionen nicht.
Warum macht man das so?
Naja stell dir vor du möchtest gerne auch die letzte Farbe, die ein Auto hatte speichern. Du wilslt aber nicht immer daran denken, überall wo die Farbe geändert werden kann, auch die vorherige Farbe zu speichern, also machst du daraus folgendes:

Java:
public void setLackFarbe(String color) {
    vorherigeLackFarbe = lackFarbe;
    lackFarbe = color;
}

immer wenn du die Lackfarbe änderst, wird jetzt die alte gespeichert. Das nennt sich Kapselung.



So und nun kommen wir zu den Funktionen zum Ändern:
Diese Funktionen (oder Methoden) sitzen eigentich in deiner Hauptklasse oder einer Verwaltungsklasse für deine Klassen. Was meine ich mit Verwaltungsklasse? Naja z. B. werden Lieder und Videos ganz häufig von einer Medienbibliothek verwaltet. also eine Klasse Medienbibliothek erstellen.
Wenn dein Programm allerdings nur Autos verwaltet, dann brauchst du dafür keine Extraklasse. Wenn du aber mehr machen willst, dann machst du eventuell eine Klasse Autobestand (oder Garage oder so), eine Klasse Kasse, etc.

Gehen wir davon aus du willst nur deine Autos verwalten, dann machen wir keine besondere Klasse.
Also bauen wir in deine Hauptklasse eine Funktion (Methode). Ich nenne es hier Funktion, weil eine Methode normalerweise eine Klasse direkt zugeordnet ist. Das ist zwar hier der Fall, da aber deine Hauptklasse eigentlich keine Klasse (kein reales Abbild) ist, nenne ich es Funktion.

Java:
private void editAuto(Auto auto) {

    System.out.println("Sie bearbeiten gerade das Auto: " + auto.getBezeichnung());
    System.out.println("Geben Sie die neue Farbe ein und drücken Sie Enter: ");
    String farbe = input.readLine(); //Achtung musst du über BufferedReader machen, das hier ist ganz abstrakt
    System.out.println("Geben Sie die neue PS-Zahl ein und drücken Sie Enter: ");
    String ps = input.readLine(); //Achtung musst du über BufferedReader machen, das hier ist ganz abstrakt

    [...]

    auto.setLackFarbe(farbe);
    auto.setPS(ps);

}

Beim Verwalten deiner Daten musst du mir nochmal sagen was das bedeuten soll, dann erklär ich dir das auch nochmal.

Beim Anzeigen gibt es eine Besonderheit. Jede Klasse hat eine Methode toString() für eine Klasse Auto sieht ein Beispiel etwa so aus:

Java:
public Sring toString() {
    return bezeichnung + " ( " + ps + ", " + farbe + " )"; 
}

Wenn dir das reicht, dann mach das einfach so, wie das ausgegeben werden soll (Formatierung, Liste oder so), das solltest du wieder da regeln, wo dann auch die tatsächliche Ausgabe erfolgt, also z. B. in einem JPanel oder einem JFrame für grafische Oberflächen, oder in der Hauptklasse wenn du eine Konsolenprogramm hat.

Hoffe das hilft erstmal weiter!
 
Mit OOP wird versucht, Objekte als Klassen zu modellieren. In Deinem Post sehe ich aber kein einziges Objekt, sondern nur Methoden wie DatenVerwalten, DatenEdit und DatenAnzeigen, die Du als eigene Klasse modellieren willst. Da bist Du auf dem Holzweg.

Ich habe einmal in Java ein Projekt für eine kleine Bibliothek erstellt. Eine Bibliothek hat Bücher und Personen, welche diese Bücher ausleihen. So wurde eine Klasse Buch und eine andere Klasse Person erzeugt. Der Datenspeicher für die Personen und Bücher sowie deren Verwaltungsfunktionen wurde in einer Klasse Bibliothek untergebracht. Dazu gehören Methoden wie addBook(), checkOut() etc. Mit drei Klassen wurde das ganze Projekt realisiert.

Bevor Du Dich in den Details verlierst, benenne zuerst Deine Objekte.
 
da einige wissen wollen was ich denn so treibe:
Na denn dann mal willkommen zu meinem Projekt - Musik lernen ...
dat ganze ist ein Swing Programm und soll folgendes leisten:
Einlesen von MIDI Daten von extern - ich habe ein Midi-Keyboard am PC und die daten werden eingelesen - status 90%
Anzeige von Noten wie auf einem Notenblatt als Grafik auf einem JPanel - zu 2/3 fertig
Editieren von Noten im extra JPanel - fertig zu 30%

Bewertung und entsprechende Scores Vergabe beim Vergleich von vorgebenen Noten und gespielten Noten - sprich ein gameprinzip - 0%
Speichern von Übungsliedern - 0%

Momentan am Basteln und Ursache des Postes - interne Verwaltung der Noten
Da ich Im Jpanel auf Mouseklicks reagiere muss ich die Noten in einem eigenen Format speichern.
Zu Erklärung - Die MIDI daten liegen zwar auch als "Liste" vor die netterweise zeitlich geordnet ist - aber für jede Note gibt es zwei einträge - einmal wann sie anfängt und einmal wenn sie endet - für meine Zwecke so unbrauchbar.
Sprich NoteAn Eintrag um zeit 44 und NoteAus Eintrag um 48

Bei der Grafischen Ausgabe gibts für die Noten eine Position auf einer X und einer Y Position

Ich habe so schon mal ein Objekt Noten aber zwei Sichtweisen - um auf das Autobeispiel einzugehen - ein Auto mit farbe und Spritverbrauch aus der sicht des Halters und Ein Auto mit KFZ Steuer Höhe und Steuerzahler aus der Sicht vom Staat.- das eine hat mit dem andren nur indirekt was zu tun ...

Eine Direkte Umsetzung von MIDI Noten auf Grafische Ausgabe geht schon mal nicht -
Da auch eine eingabe über Texteingabe gehen soll habe ich dann noch ein drittes Format der Note als String - eine von mir erstellte Darstellung die die Noten auf Stringkürzel runterbricht.

so gesehen zwar ein Objekt aber 3 verschiedene Ansätze sie zu sehen.

so zum Code:

Code:
class ZeichneNote  { // die classe ist eine reine Classe zum zeichen der Noten - statt DrawEllipse halt Draw note
    int px4step = 8; // grösse pixel per step - 1 step ist halber noten linienabstand
    int takt4line = 4;  // take pro zeile
    int posX =10, posY = 10; // position der Notenzeile

int zeigeNote (Graphics zn, String slotnote, int tickX) {} // zeichen Note C-H auf Pos X
void zeigePause(Graphics zp, char styp, int sposx) {} // zeichen von Pausenzeichen
void zeigeZeile (Graphics zz,int taktanz, int nzposx, int nzposy) {} //zeiche Notenlinien
void showBassKey (Graphics2D zb) {} //zeiche ein Bassschlüssel
void showViolinKey (Graphics2D zv) {} // zeiche ein Violinschlüssel
}

public class NotenBlattData {  // hier die sichtweise Der Noten aus Grafischer sicht
    
    int px4step, blxpos, blypos;
    ArrayList<NotenGfx> lieddata = new ArrayList<NotenGfx>();

    public class NotenGfx {
        int zeile,slot, link; // link ist verweis auf den index im LiedList
    }
}

public class NoteData { // so möchte ich nun die Noten speichen
    char note,art;
    int octave;  // octave 0 ist Sonderzeichen
    long tick;
    boolean is, extend, halten;
}

public class LiedList {  // speicherung der daten für ein ganzes musikstück

    ArrayList<NoteData> lieddata = new ArrayList<NoteData>();
}

public class MidiPort {} alles was mit MIDI zu tun hat - einlesen usw..

public class EditJPanel extends javax.swing.JPanel {} // das Fenster zum editieren der Noten zb - Note eins höher oder Note verkürzen usw..
benutzt natürlich ZeichneNote
ich denke ich hab das Wichtigste ... den code drin und das Main drumherrum schenke ich mir mal ...

Nachtrag:
Ich tendiere im Moment zu der Trennung:

MidiPort - macht alles aus der Sicht MIDI daten
LiedList - speichert den Song im eigenen Notenformat Note
NotenBlatt - macht alles für die Grafische Darstellung

und alle 3 tauschen sich über Note aus .
 
Zuletzt bearbeitet:
Ok, also ich würde dir erst einmal UML empfehlen, das hilft bei solchen Projekte weiter, einfach schon des Überblickes wegen.

Aber um dein Problem mal anzugehen. Eine Klasse Note für dich macht wohl doch viel Sinn. Sowei ich das weiß hat eine Note in der Musik mehrere Parameter eine Klasse wäre also nun:

Java:
public class Note implements NotationMark {

    private int value = 0; //definieren wir 0 mal als c, 1 = d, 2 = e, 3 =f usw.
    private boolean sharp = false, flat = false;
    private byte octave = 0; // octave = und value = 0 ergeben das tiefste C
    private float beats = 1; //Eine Viertelnote, 2 wäre eine halbe, 0.5 eine Achtel und so weiter (nur Beispiel) 

}

Damit sollten ALLE deine Klassen umgehen können.
Wie du vielleicht bemerkt hast, habe ich etwas hinzugefügt: "implements NotationMark".

Was das tut erkläre ich gleich, aber erstmal vorneweg: Nutze Methoden. Meinetwegen nutze auch noch weitere Klassen. Aber bauen dir Immer Methoden bzw. Funktionen und Konstruktoren. die deine Klassen ineinander transformieren.

Beispiel Auto: Das Auto für den Halter mit Farbe und Spritverbrauch und für den Staat mit Steuerklasse und Halter.
1.
Der Halter würde wohl nicht Auto zugeordnet, sondern andersrum, denn der Halter zahlt Steuern und nicht das Auto. Also ist der Halter kein Attribut des Autos.
2.
Steuerklasse und Spritverbrauch könnten Attribute des Autos sein, also meine Frage andersherum, ist "Alter" ein Attribut eines Menschen? Nein! Sowohl Steuerklasse als auch Spritverbrauch sind abhängig vom Motor.
Also hat ein Auto entweder 2 Attribute Hubraum und Motortyp (Benzin / Diesel / Gas / Elektro)
Oder dem Auto wird ein Motor zugeordnet, der die Werte hat.
getSetuerklasse() und getSpritverbraucht() wären also Methoden, die den entsprechenden Wert berechnen, aus den Attributen des Autos.

Wenn du also die Note korrekt abbildest, solltest du daraus alles andere berechnen können.

Mache als keine Klasse ZeichneNote sonder eine Methode getGraphic2D() in der Klasse Note!

Nun zum "Interface" da wird es etwas komplexer.
Ich implementiere ein Interface mit den Namen NotationMark.
Das folgende Funktion ernthält:

Java:
public interface NotationMark {

    public Graphics2D paintMark(int height, int width);

}

Das bedeutet, dass die Klasse Note jetzt diese Funktion implementieren muss.
Warum? Nunja, wir können einfach alles was aus diesem Interface machen.
Du willst ein Pausenzeichen? Dann mache eine Klasse BreakMark.
Einen Notenschlüssel? Baue eine Klasse Clef.
Und alle implementieren diese Funktion, du musst sie nur jedesmal neu mit leben Füllen, ist ja auch klar, eine Pause sieht anders aus als eine Note und ein Notenschlüssel sowieso.

Was ist der Vorteil? Du kannst dir einfach eine Liste aus NotationMarks bauen und dein JPanel kann über diese Funktion einfach alle Noten, Pausen, Notenschlüssel zeichnen lassen.

Du kannst einfach weitere solche Interfaces basteln. Sie sind quasi Schnittstellen.
Diese Interfaces bauen dir nur leere Funktionen, Aber du kannst sie von mehreren Klassen
implementieren lassen und so Inhalte generalisieren.

So ich hoffe dieses Wissen hiflt dir etwas weiter. Versuche einfach deine Klassen möglischt weit zu abstrahieren und auf die Grundwerte zurückzuführen.
 
Wenn man vom reinen OOP Ansatz ausgeht währe es natürlich besser wenn die class Note alles könnte
ABER - dagegen wehrt sich alles war ich mal vor Urzeiten gelernt habe
! gehe Sparsam um mit Speicherplatz !

Wenn ich die class Note mit je Menge Intelligenz ausstatte und sie dann 100 mal erzeuge um ein komplettet Lied darstellen zu können - so ist das doch Platzverschwendung pur - 100 mal die Functionen im Speicher - der platzt doch :)

darum war ja mein Ansatz die Class note nur als Datenspeicher zu nutzen und dort nötige Werte abzulegen.

Code:
class Note {
int octave, note, playdauer, xpos,ypos, breitegfx;
// note C=1 usw playdauer ergibt viertel,achtel usw breitegfx breite Grafisch
}
 
Zuletzt bearbeitet:
Zurück