Exercise "Understanding access control "





  • Hallo Herr Goik,

    Ich habe noch eine Frage.

    Zur Bearbeitung dieser Aufgabe habe ich in Class Alpha einen public String name angelegt.
    In Class Beta (gleiches package) wollte ich nun den public String name ändern.
    Es hieß doch, dass bei public quasi jeder Zugriff auf Methoden und Attribute hat.
    Warum wird mir hier aber die Namensänderung verboten (das Attribut name wird auch gar nicht angezeigt in Class Beta) ?

    Danke im Voraus!

    Sarah Mauff



  • @Mauff Ich probiere mal zu verstehen, was Sie möglicherweise beabsichtigen:

    public class Alpha {
       public String name;
            
       void print() {
           System.out.println(name); // o.K.
       }
    }
    

    Die Instanzvariable name kann in allen Methoden der Klasse Alpha verwendet werden. Man sagt, die Klasse Alpha ist der Bezugsrahmen (Scope) von name. In der von Alpha völlig unabhängigen Klasse Beta ist diese Variable daher unsichtbar. Daran ändert auch das identische Package nichts:

    public class Beta {
       void print() {
          System.out.println(name); // Error: Cannot resolve symbol 'name'
       }
    }
    

    Was Sie möglicherweise verwechseln, ist der Zugriff auf Instanzen von Alpha in beliebigen Kontexten, auch beispielsweise innerhalb von Methoden in Beta:

    public class Beta {
       void print() {
          Alpha a = new Alpha(...);
            ...
          System.out.println(a.name); // o.K.
       }
    }
    

    Es gibt übrigens zwei konzeptionell total verschiedene Möglichkeiten, den Zugriff auf name durch die Klasse Beta dennoch zu erreichen:

    1. Sie definieren name in Alpha durch das Schlüsselwort static nicht als Instanz-, sondern als Klassenvariable (was natürlich eine völlig andere Semantik darstellt):

       public class Alpha {
          static public String name;
            ...
      

      Jetzt ist name kein Instanz-, sondern ein Klassenattribut in Alpha. Auf dieses können Sie dank der public Deklaration u.A. aus der Klasse Beta heraus zugreifen:

      public class Beta {
         void print() {
            System.out.println(Alpha.name); // o.K.
         }
      }
      
    2. Sie lassen die Klasse Beta von Alpha erben:

      public class Beta extends Alpha {
         void print() {
             System.out.println(name); // o.K.
         }
      }
      

      Da Beta nun die Klasse Alpha erweitert, ist der Zugriff (wiederum dank public) möglich. In diesem Fall reicht es aber, in der Basisklasse Alpha den stärker einschränkenden Modifier protected zu verwenden:

      public class Alpha {
          protected String name;
        ...
      
      

      Beim Ersatz durch private hingegen wäre der Zugriff in der abgeleiteten Klasse Beta wiederum verboten.

    Geben Sie bitte nach Möglichkeit ein Codebeispiel oder eine andere Erläuterung, falls meine Antwort Ihre Frage nicht treffen sollte.



  • @Dr-Martin-Goik Sie haben die Frage tatsächlich verstanden. Leider schreibe ich häufig wie ich denke..

    Kann man zusammenfassend also sagen, dass man durch public von Beta aus zwar auf die Methoden von Alpha zugreifen kann, jedoch nicht auf spezielle Variablen (sofern diese nicht durch Methoden aufgerufen werden)?

    Gruß

    Sarah Mauff



  • @Mauff: Ich glaube, der Schlüssel zum Verständnis liegt im this Keyword. Es ist wichtig zu sehen, dass es sich bei name um eine Instanzvariable handelt. Sie kann daher grundsätzlich nur über eine Instanzreferenz verwendet werden:

    Alpha a = new Alpha(...);   // Erzeugung einer Instanz der Klasse Alpha und
                                // Zuweisung der Referenz an die Variable a.
    ...
    
    System.out.println(a.name); // Zugriff über die Variable a zur Instanz
                                // und dann weiter auf das Attribut name.
    

    Nun ist Ihnen aufgefallen, dass Sie name nicht in der Klasse Beta verwenden können. Man kann sich fragen, wieso dies aber innerhalb z.B. einer Methode der Klasse Alpha ohne Verwendung einer Instanzvariablen möglich ist:

    public class Alpha {
       public String name;
          
       void print() {
           System.out.println(name); // Verwendung ohne xyz.name, dennoch Instanzbezugsrahmen!
       }
    }
    

    Der Zugriff wird besser (hoffentlich!) besser verständlich, wenn wir (unnötigerweise) zur Verdeutlichung explizit das Schlüsselwort this verwenden:

    public class Alpha {
       public String name;
       
       void print() {
           System.out.println(this.name); // this steht für die Instanz                       
       }
    }
    

    Ein komplettes Beispiel:

    Alpha a = new Alpha();                                                                    
    a.name = "Sue";
    a.print();
    

    In diesem Fall enthält die Variable a genau dieselbe Referenz wie this innerhalb der
    print() Methode der Klasse Alpha.

    Innerhalb der print() Methode darf ich den this. Anteil auch weglassen und wie üblich nur name alleine verwenden (außer bei einem Konflikt mit einer Methoden-lokalen Variable).

    Da das Instanzattribut name zur Klasse Alpha »gehört«, macht this.name in der Klasse Beta genauso wenig Sinn, wie die Verwendung von name allein.



  • @Dr-Martin-Goik ah ok, jetzt habe ich es verstanden. Vielen Dank für Ihre Antwort!


Log in to reply