Java class design #1

Use access modifiers: private, protected, and public.

Java przykłada bardzo dużą uwagę do tego kto, kiedy i jak może ingerować w elementy składowe danej klasy. Możliwość modyfikowania zmiennych oraz wywoływania metod możemy ograniczać nadając im jeden z czterech modyfikatorów dostępu. W tym artykule szczegółowo omówimy każdy z nich.


Na skróty:

Repozytorium z przykładami [GitHub]


Public

Modyfikator public, nadaje najmniej restrykcyjne ograniczenia. Właściwie powinienem powiedzieć, że całkowicie te ograniczenia usuwa.

public int counter = 0;
public void getCounter(){return counter;}

Zadeklarowane w ten sposób zmienne i metody są widoczne dla każdego obiektu w systemie. Zmienne public w żaden sposób nie są chronione przed nadpisaniem przez inne obiekty, więc możemy bez problemu zrobić coś takiego:

public class Car {
  public int speed = 0;
}
public class Driver {
  public static void main(String[] args){
    Car car = new Car();
    car.speed = 120;
  }
}

W rzeczywistym świecie kierowca nie ustawia ot tak sobie prędkości samochodu. Musi wcisnąć pedał gazu, a całą robotę odwala silnik… I też, żebyśmy nie wiem jak bardzo chcieli, to w ciągu sekundy nie przyśpieszy od 0 do 120 km/h. Również w naszym oprogramowaniu powinniśmy wystrzegać się takich rozwiązań.

Protected

Modyfikator protected, jest nieco bardziej restrykcyjny od public. Zapewnia on swobodny dostęp do zmiennych lub metod, ale pod warunkiem, że klasa obiektu, który z nich korzysta spełnia jeden z dwóch warunków:

  • Jest zadeklarowana w tej samej paczce (ang. package).
  • Dziedziczy po klasie, która zawiera te elementy protected.

Rozszerzmy poprzedni przykład o zmienną protected boolean engineStarted. Klasa Driver jest w tej samej paczce co klasa Car, więc może korzystać ze zmiennej engineStarted, tak jakby ta była publiczna.

package com.javathehat.classdesign;
public class Car {
  public int speed = 0;
  protected boolean engineStarted = false;
}
package com.javathehat.classdesign;
public class Driver {
  public static void main(String[] args){
    Car car = new Car();
    car.engineStarted = true;
    car.speed = 120;
  }
}

Ale wystarczyłoby zmienić deklarację paczki w dowolnej z tych klas na przykład na: com.javathehat.classdesign2 i powyższy kod już by się nie skompilował. Chyba, że klasa Driver rozszerzała by klasę Car, co oczywiście nie ma najmniejszego sensu i byłoby świetnym przykładem złego zaprojektowania systemu.

Default

Choć nie jest to zalecana praktyka, możemy nie użyć żadnego z trzech głównych słów kluczowych (public, protected, private). Wtedy mamy do czynienia z dostępem domyślnym, zwanym potocznie „package private”. W takim wypadku metoda lub zmienna widoczna jest wyłącznie dla wszystkich klas będących w obrębie tej samej paczki.

Tutaj, do poprzedniego przykładu dodaliśmy zmienną fuel, która nie posiada żadnego modyfikatora. Możemy z niej korzystać w klasie Driver, ponieważ znajduje się w tej samej paczce co klasa Car.

package com.javathehat.classdesign;
public class Car {
  public int speed = 0;
  protected boolean engineStarted = false;
  int fuel = 100;
}
package com.javathehat.classdesign;
public class Driver {
  public static void main(String[] args){
    Car car = new Car();
    car.engineStarted = true;
    car.speed = 120;
    car.fuel = 50;
  }
}

Private

Ostatni, najbardziej restrykcyjny modyfikator dostępu. Jeśli oznaczymy metodę lub zmienną słowem kluczowym private– możemy z nich korzystać tylko w klasie, w której je zadeklarowaliśmy.

package com.javathehat.classdesign;
public class Car {
  public int speed = 0;
  protected boolean engineStarted = false;
  int fuel = 100;
  private long engineNumnber = 101961412;
}

W tym przypadku ze zmiennej engineNumber może korzystać tylko klasa Car, żadna inna klasa nie będzie nawet świadoma istnienia takiej zmiennej.

To wszystko. Prosty i przyjemny wstęp do projektowania klas w Javie. W następny artykule zajmiemy się nadpisywaniem metod.