# Selbstinstanzierung



## TheBlackPitcher (15. Nov 2010)

```
public class Uhrenanzeige
{
    private Nummernanzeige Sekunden;
    private Nummernanzeige Minuten;
    private Nummernanzeige Stunden;
    private Uhrenanzeige Wecker;
    private boolean displaySekunden;
    private boolean englishTimestamp;
    private boolean wecker;
    private int[] weckzeit = new int [3];
    private static boolean instanz;
    public Uhrenanzeige (){
        Sekunden    = new Nummernanzeige(60);
        Minuten     = new Nummernanzeige(60);
        Stunden     = new Nummernanzeige(24);
        Wecker      = new Uhrenanzeige();
        displaySekunden = false;
        englishTimestamp = false;
    }
```
ist es möglich irgendwie diese Zeile(Wecker      = new Uhrenanzeige(); ) zu realisieren ohne bei einer Instanzierung einen Fehler zu erhalten??


----------



## SlaterB (15. Nov 2010)

was soll denn deiner Meinung nach passieren?
das Uhrenanzeige-Objekt erstellt sich ein zweites Uhrenanzeige-Objekt Wecker (Variablen klein schreiben!)

und das zweite Uhrenanzeige-Objekt Wecker? ist ja auch eine Uhrenanzeige, soll das auch einen Wecker haben -> Endlosschleife
oder doch lieber nicht? dann füge z.B. einen boolean-Parameter in den Konstruktor ein true/false für Wecker ja/nein


----------



## bygones (15. Nov 2010)

SlaterB hat gesagt.:


> oder doch lieber nicht? dann füge z.B. einen boolean-Parameter in den Konstruktor ein true/false für Wecker ja/nein


argh... mir grauts immer vor solchen boolean schaltern ;-)

mir erscheint da das Design fragwürdig, das würde ich eher angehen.... Uhranzeige ist gleichzeitig Anzeige und Wecker etc etc


----------



## TheBlackPitcher (15. Nov 2010)

ich habs auch schon mit einem statischen Object versucht zu überprüfen ob Wecker schonmal erstellt wurde, um eine Endlosschleife zu umgehen, leider führte dies auch zu einem error beim instanzieren.
Die Aufgabe ist eine Lernaufgabe aus der Schule welche ich versucht habe, möglichst optimal zu schreiben um wenig code zu erzeugen. Deshalb wollte ich wenn es geht vermeiden die struktur komplett zu ändern.

edit: ich hatte zuerst deine Lösung falsch verstanden. Nachdem ich deinen Lösungsvorschlag überdacht habe und diesen befolgt habe, war die lösung erfolgreich.


----------



## Andi_CH (17. Nov 2010)

TheBlackPitcher hat gesagt.:


> ist es möglich irgendwie diese Zeile(Wecker      = new Uhrenanzeige(); ) zu realisieren ohne bei einer Instanzierung einen Fehler zu erhalten??




Stack overflow in Null Komma nichts ist das Einzige was hier passiert.

Du sagst, dass eine Uhrenanzige einen Wecker hat, der eine Uhrenanzige hat die einen Wecker hat der ........ (Da war doch mal was mit einem Mann und einem hohlen Zahn ;-) )

Warum hat eine Klasse eine Referenz auf sich sich selbst? Das tönt nach verketteter Liste und die kann nicht im Konstruktor selbst aufgebaut werden.

Du möchtest hier IMHO etwas ganz anderes. Du möchtest einen Wecker mit Anzeige.

Wie wärs mit einer Klasse Wecker und die hat eine Referenz auf Uhrenanzeige hat?

Stell dir mal for du baust noch eine Wanduhr und eine Armbanduhr und beide haben auch Uhrenanzeigen ...

Die Anzeige muss vermutlich nicht einmal wissen wo sie hingehört.

[EDIT]
Jetzt fällt mir gerade auf, dass du "Wecker = new....." gross geschrieben hast - was wolltest du damit bezwecken? Wecker ist ja gar keine Variable? Ich glaube wir reden aneinander vorbei.

(wecker ist eine boolean)


----------



## TheBlackPitcher (17. Nov 2010)

Auch wenn ich dieses Problem bereits gelöst habe, werde ich jetzt hier mal den vollständigen Code posten um der Allgemeinen Verwirrung etwas entgegen zu wirken.


```
public class Nummernanzeige
{
    private int wert, limit;
    
    public Nummernanzeige(int limit) {
        
        this.limit  = limit;
        wert        = 0;
        
    }
    
    public int setzeWert(int wert) {
        
        if(wert > limit){
            
            int teiler =(int)(wert/limit);
            this.wert += wert - (limit*teiler);
            
            return teiler;
        }
        else{
            
            this.wert = wert;
            
            return 0;
        }
        
    }
    
    public int gibWert() {
        
        return wert;
    }
    
    public int erhoehen(int wert) {
        
        if((this.wert + wert) >= limit){
            
            int teiler = (int)((wert + this.wert) / limit);
            this.wert += wert - (limit*teiler);
            
            return teiler;
        }
        else{
            
            this.wert += wert;
            
            return 0;
        }
    }
    
    public int erhoehen(){
        
       return erhoehen(1);
    }
    
}

public class Uhrenanzeige
{
    private Nummernanzeige  sekunden;
    private Nummernanzeige  minuten;
    private Nummernanzeige  stunden;
    private Uhrenanzeige    weckerObj;
    
    private boolean         displaySekunden;
    private boolean         englishTimestamp;
    private boolean         wecker;
    private boolean         mitWecker;
    
    private int[]           weckzeit = new int [3];
    
    public Uhrenanzeige ( boolean wecker ){
        constructorVar();
        constructorWecker();
    }
    
    private void constructorVar(){
        sekunden            = new Nummernanzeige(60);
        minuten             = new Nummernanzeige(60);
        stunden             = new Nummernanzeige(24);
        displaySekunden     = false;
        englishTimestamp    = false;
    }
    
    private void constructorWecker(){
        
        if(wecker){
            
            weckerObj       = new Uhrenanzeige(false);
            mitWecker       = true;
            
        }
        else{
            
            mitWecker       = false;
            
        }
        
    }
    
    public String gibUhrzeit(){
        String suffix;
        String ergebnis         = "";
        
        if(englishTimestamp && stunden.gibWert() > 12){
            
            if(stunden.gibWert() == 0){
                
                int stunden     = 12;
                ergebnis        = stunden + ":" + minuten.gibWert();
                
            }
            else{
                
                ergebnis        = (stunden.gibWert() - 12) + ":" + minuten.gibWert();
                
            }
            
            suffix      = "PM";
            
        }
        else if(englishTimestamp){
            
            if(stunden.gibWert() == 0){
                
                int stunden     = 12;
                ergebnis        = stunden + ":" + minuten.gibWert();
                
            }
            else{
                
                ergebnis        = stunden.gibWert() + ":" + minuten.gibWert();
            
            }
            
            suffix              = "AM";
            
        }
        else{
            
            ergebnis            = stunden.gibWert() + ":" + minuten.gibWert();
            suffix              = "";
            
        }
        if (displaySekunden){
            
            ergebnis           += ":" + sekunden.gibWert();
            
        }
        if(suffix != ""){
            
            return ergebnis + " " + suffix;
            
        }
        else{
            
            return ergebnis;
            
        }
        
    }
    
    public void setzeUhrzeit(int stunden, int minuten, int sekunden) {
        this.sekunden.setzeWert(sekunden);
        this.minuten.setzeWert(minuten);
        this.stunden.setzeWert(stunden);
    }
    
    public void konfiguriereZeitformat(boolean displaySekunden, boolean twelveHour){
        this.displaySekunden    = displaySekunden;
        englishTimestamp        = twelveHour;
        
        if(wecker){
            
            weckerObj.konfiguriereZeitformat(displaySekunden, twelveHour);
            
        }
        
    }
    
    public String taktsignalGeben(){
        int increaser   = sekunden.erhoehen();
        
        if(increaser != 0){
            
           increaser    = minuten.erhoehen(increaser);
           
           if(increaser != 0) {
               
               stunden.erhoehen(increaser);
               
            }
            
        }
        
        if(gibUhrzeit() == weckerObj.gibUhrzeit()){
            
            return "ring ring ring";
            
        }
        else{
            
            return gibUhrzeit();
            
        }
        
    }
    
    public void setzeWecker(int stunden, int minuten, int sekunden){
        
        if(mitWecker){
            
            weckzeit[0] = stunden;
            weckzeit[1] = minuten;
            weckzeit[2] = sekunden;
            
            wecker      = true;
            
            weckerObj.setzeUhrzeit(stunden,minuten,sekunden);
            
        }
        
    }
    
    public void schlummern(){
        
        if(mitWecker){
            
            weckerObj.setzeWecker(weckzeit[0],(weckzeit[1] + 10),weckzeit[2]);
            
        }
        
    }
    
}
```
<<dies ist eine fehlerhafte Lösung, ich entschuldige mich nochmals förmlich für meine fälschliche Annahme das der Code funktionieren würde.
Im anschluss der verbesserte Code.


```
public class Nummernanzeige
{
    private int wert, limit;
    
    public Nummernanzeige(int limit) {
        
        this.limit  = limit;
        wert        = 0;
        
    }
    
    public int setzeWert(int wert) {
        
        if(wert > limit){
            
            int teiler =(int)(wert/limit);
            this.wert += wert - (limit*teiler);
            
            return teiler;
        }
        else{
            
            this.wert = wert;
            
            return 0;
        }
        
    }
    
    public int gibWert() {
        
        return wert;
    }
    
    public int erhoehen(int wert) {
        
        if((this.wert + wert) >= limit){
            
            int teiler = (int)((wert + this.wert) / limit);
            this.wert += wert - (limit*teiler);
            
            return teiler;
        }
        else{
            
            this.wert += wert;
            
            return 0;
        }
    }
    
    public int erhoehen(){
        
       return erhoehen(1);
    }
    
}

public class Uhrenanzeige
{
    private Nummernanzeige  sekunden;
    private Nummernanzeige  minuten;
    private Nummernanzeige  stunden;
    private Uhrenanzeige    weckerObj;
    
    private boolean         displaySekunden;
    private boolean         englishTimestamp;
    private boolean         wecker;
    private boolean         mitWecker;
    
    private int[]           weckzeit = new int [3];
    
    public Uhrenanzeige ( boolean wecker ){
        constructorVar();
        constructorWecker(wecker);
    }
    
    private void constructorVar(){
        sekunden            = new Nummernanzeige(60);
        minuten             = new Nummernanzeige(60);
        stunden             = new Nummernanzeige(24);
        displaySekunden     = false;
        englishTimestamp    = false;
    }
    
    private void constructorWecker(boolean wecker){
        
        if(wecker){
            
            weckerObj       = new Uhrenanzeige(false);
            mitWecker       = true;
            
        }
        else{
            
            mitWecker       = false;
            
        }
        
    }
    
    public String gibUhrzeit(){
        String suffix;
        String ergebnis         = "";
        
        if(englishTimestamp && stunden.gibWert() > 12){
            
            if(stunden.gibWert() == 0){
                
                int stunden     = 12;
                ergebnis        = stunden + ":" + minuten.gibWert();
                
            }
            else{
                
                ergebnis        = (stunden.gibWert() - 12) + ":" + minuten.gibWert();
                
            }
            
            suffix      = "PM";
            
        }
        else if(englishTimestamp){
            
            if(stunden.gibWert() == 0){
                
                int stunden     = 12;
                ergebnis        = stunden + ":" + minuten.gibWert();
                
            }
            else{
                
                ergebnis        = stunden.gibWert() + ":" + minuten.gibWert();
            
            }
            
            suffix              = "AM";
            
        }
        else{
            
            ergebnis            = stunden.gibWert() + ":" + minuten.gibWert();
            suffix              = "";
            
        }
        if (displaySekunden){
            
            ergebnis           += ":" + sekunden.gibWert();
            
        }
        if(suffix != ""){
            
            return ergebnis + " " + suffix;
            
        }
        else{
            
            return ergebnis;
            
        }
        
    }
    
    public void setzeUhrzeit(int stunden, int minuten, int sekunden) {
        this.sekunden.setzeWert(sekunden);
        this.minuten.setzeWert(minuten);
        this.stunden.setzeWert(stunden);
    }
    
    public void konfiguriereZeitformat(boolean displaySekunden, boolean twelveHour){
        this.displaySekunden    = displaySekunden;
        englishTimestamp        = twelveHour;
        
        if(wecker){
            
            weckerObj.konfiguriereZeitformat(displaySekunden, twelveHour);
            
        }
        
    }
    
    public String taktsignalGeben(){
        int increaser   = sekunden.erhoehen();
        
        if(increaser != 0){
            
           increaser    = minuten.erhoehen(increaser);
           
           if(increaser != 0) {
               
               stunden.erhoehen(increaser);
               
            }
            
        }
        
        if(gibUhrzeit() == weckerObj.gibUhrzeit()){
            
            return "ring ring ring";
            
        }
        else{
            
            return gibUhrzeit();
            
        }
        
    }
    
    public void setzeWecker(int stunden, int minuten, int sekunden){
        
        if(mitWecker){
            
            weckzeit[0] = stunden;
            weckzeit[1] = minuten;
            weckzeit[2] = sekunden;
            
            wecker      = true;
            
            weckerObj.setzeUhrzeit(stunden,minuten,sekunden);
            
        }
        
    }
    
    public void schlummern(){
        
        if(mitWecker){
            
            weckerObj.setzeWecker(weckzeit[0],(weckzeit[1] + 10),weckzeit[2]);
            
        }
        
    }
    
}
```


----------



## SlaterB (17. Nov 2010)

komische Lösung wenn doch der Parameter des Konstruktors nirgendwo verwendet wird,
das Klassenattribut wecker anfangs immer false ist

bei setzeWecker könnte man denken, dass wecker auf true gesetzt wird, was aber einerseits nicht hilft, die NullPointerException wegen nicht vorhandenen Wecker-Objekt eine Zeile später zu verhindern,
und andererseits kommt es dazu auch nie: anfangs ist wecker false -> mitWecker ist auch false, keine Möglichkeit das je zu ändern

na nicht tragisch, Schritt für Schritt verbessern, dann wird das schon bald


----------



## TheBlackPitcher (17. Nov 2010)

Die Lösung ist ziemlich konfuse und ich hätte es Persönlich auch anders gelöst, aber es sollte ein Lösungsbeispiel für die Klasse sein und so wenig Verzweigungen wie möglich aufweisen.
Was die Sache mit der Variablen wecker angeht. Der Parameter genießt ja wie bekannt ist Vorrang deshalb funktioniert dieses Konstrukt sehr wohl. Ich hätte lieber eine neue Klasse gemacht und in dieser 2 Instanzen der Klasse Uhrenanzeige genutzt. Jedoch wollte ich mit diesem Beispiel zeigen das der Konstruktor der letzte Punkt in einer Klasse darstellt um dinge Ausserhalb einer Methode ohne Parameter zu zu greifen.
Ps: der Parameter des konstruktors wird in den ausgelagerten Funktionen benutzt.
Jetzt weiss ich aber nicht ob ich diesem ach konstant über einen Parameter die Variable weiter vermitteln soll. Aber scheinbar funktioniert dies auch so.
...
Ps.: Sie hatten natürlich recht ^^da nach dem Refactoring der ausgelagerte Teil kein Parameter hatte wurde immer ohne Wecker ausgeführt.
Danke für den Hinweis und entschuldige die Behauptung das dies oben Funktioniert haben soll.


----------



## Andi_CH (17. Nov 2010)

Nur schon die Formulierung "mitWecker" heisst für mich in der OO-Welt ganz einfach: na dann gib ihr doch einen Wecker und Wecker ist eine eigene Klasse. (Wenn die Referenz mWecker null ist hat die Uhr halt keinen)

SW-Entwicklung beginnt nun mal nicht mit Programmieren - da verliert man zu schnell den Überblick.

Was so in 5 Sekunden in meinem Kopf ensteht muss ja nicht gleich jeder Diskussion standhalten, aber in den Grundzügen simmt es sicher ...


----------



## TheBlackPitcher (17. Nov 2010)

So hätte ich das wohl auch gemacht wenn ich nicht an feste Klassendiagramme des Lehrers gebunden gewesen wäre, weil es so einfach übersichtlicher ist.
Jedoch habe ich eine Frage zu dem Diagramm, welches sie erstellt haben. Wofür stehen die Zahlen?


----------



## Andi_CH (17. Nov 2010)

Du bist ganz sicher nicht an Programmierfehler gebunden - Wecker = new Wecker() ist schlicht und einfach doppelt falsch! Einerseits ist es als Statement ungültig und wenn auch man es korrigiert

```
class Wecker {
  Wecker myWecker;

  public Wecker(){
    myWecker = new Wecker();
  }
}
```
knallt es, weil innerhalb des Konstruktors, bedingt durch die Rekursion, beliebig viel Memory verbraucht wird.

Wenn ich keine weiteren Klassen modellieren dürfte, hätte jede meiner Uhren genau einen Wecker, den ich aber permanent deaktivieren könnte.

====== Ein bisschen OT ;-)

Anderes Thema: Was verstehst du von UML? Was hast du darüber schon gehört? (Die Frage stelle ich aus reinem Interesse was die heutige Ausbildung betrifft, denn wir haben zuerst mit UML begonnen und dann, mit kleinem Rückstand, das in Java umgesetzt, was wir in UML modeliert haben.

Die Assoziation zwischen Uhr und Anzeige:
Die 1 bei Anzeige heisst, dass eine Uhr genau eine Anzeige hat.
Die 1 bei Uhr heisst, dass eine Anzeige zu genau einer Uhr gehört
-> Nach diesem Modell gibt es keine Uhren ohne Anzeige, aber auch keine zwei oder mehreren Anzeigen. Es sagt aber auch aus, dass eine Anzeige von genau einer Uhr gesteuert wird, was in der Realität seöbstverständlich erscheint, aber im SW-Design trotzdem modelliert werden muss.


Uhr - Wecker
0..* bei Wecker - Eine Uhr hat keinen bis beliebig viele Wecker
1 bei Uhr - Ein bestimmter Wecker gehört zu genau einer Uhr.

-> Es gibt Uhren ohne Wecker und es gibt Uhren mit mehreren Weckern - mein Idee ist, dass ein Wecker nur für eine Weckzeit und Weckart zuständig ist. Mein Radiowecker kann einerseits piepsen und andererseits zu einer anderen Zeit den Radio aktivieren - für mich zwei Wecker
Wenn du ausdrücken möchtest dass eine Uhr 0 - 2 Wecker hat, ist auch das kein Problem - einfach 0..2 hinschreiben - Uhren ohne Wecker gibt es nicht? ok, dann halt 1..2 hinschreiben ...


----------



## TheBlackPitcher (17. Nov 2010)

Als erstes haben wir Struktogramme gebastelt weil wir mit strukturierter programmierung angefrangen haben, dann haben wir programmiert, dann kam oop und uml ist die Planung von Projekten eine universeller Standart zur Darstellung wie das Programm in einer Beliebigen Programmiersprache später funktionieren soll, glaube ich zumindest. XD


----------



## Andi_CH (18. Nov 2010)

Hm - also keine fundierte UML Ausbildung - finde ich persönlich schade.
(UML ist übrigens nicht für die Planung geeignet, sondern dazu da, eine Aufgabenstellung zu modellieren, sowie Architektur und Design aufzuzeigen)

Meistens steht man heute ja schon vor einem grossen Haufen Code, wenn man was machen soll. Ich kann mir nur sehr schlecht vorstellen wie etwas funktioniert, wenn ich nur den Code vor mir habe - ein Diagramm sagt mir mehr.


----------

