Klasa Math
●
Klasa Math zawiera metody służące do
wykonywania podstawowych operacji
matematycznym, takich jak np. potęgowanie,
logarytmowanie, pierwiastkowanie oraz obliczanie
wartości z funkcji trygonometrycznych
●
Klasa Math nie wymaga jawnego importowania – jej
składowe są dostępne domyślnie
●
W Javie dostępna jest również inna wersja tej
biblioteki o nazwie StrictMath, zawierająca
implementacje wg. FDML (
Freely Distributable Math
Library
)
Klasa Math
●
Wszystkie składowe udostępniane przez klasę Math
są
statyczne
, co oznacza, że są dostępne bez
konieczności tworzenia obiektów tej klasy
●
Dostęp do składowych klasy Math uzyskuje się
poprzez wywoływanie ich wprost z klasy, a nie (jak
to dzieje się np. z metodami klasy String) z obiektu
takiej klasy
●
Np. wywołanie metody charAt klasy String wymaga
istnienia obiektu klasy String, na rzecz którego
wywołuje się tę metodę
Metoda charAt jest niestatyczna, więc
musi być wywoływana jest z obiektu
klasy String; próba wywołania jej z
klasy (np. String.charAt())
spowoduje błąd kompilacji
Przykład
String str = ”ABC”;
char ch = str.charAt(0); // 'A”
double sin0 = Math.sin(0);
Metoda sin klasy Math jest
statyczna, dlatego wywołuje się
ją wprost z klasy (nie z obiektu)
Użyteczne składowe klasy Math
własność:
static double E;
przybliżenie wartości stałej
e
(tzn. podstawy
logarytmu naturalnego)
przykład:
:
System.out.println(Math.E); // 2.718281828459045
:
Użyteczne składowe klasy Math
własność:
static double PI;
przybliżenie wartości stałej
π
przykład:
:
System.out.println(Math.PI); // 3.141592653589793
:
Użyteczne składowe klasy Math
metoda:
static double abs(double a);
static float abs(float a);
static int abs(int a);
static long abs(long a);
obliczenie wartości bezwzględnej argumentu
przykład:
:
System.out.println(Math.abs(-Math.PI));
// 3.141592653589793
:
Użyteczne składowe klasy Math
metoda:
static double acos(double a);
obliczenie wartości funkcji
arccos(a)
przykład:
:
System.out.println(Math.arccos(-1.0));
// 3.141592653589793
:
Użyteczne składowe klasy Math
metoda:
static double asin(double a);
obliczenie wartości funkcji
arcsin(a)
przykład:
:
System.out.println(Math.arcsin(1.0));
// 1.5707963267948966
:
Użyteczne składowe klasy Math
metoda:
static double atan(double a);
obliczenie wartości funkcji
arctg(a)
przykład:
:
System.out.println(Math.arctg(0.0)); // 0.0
:
Użyteczne składowe klasy Math
metoda:
static double cbrt(double a);
obliczenie wartości pierwiastka sześciennego
przykład:
:
System.out.println(Math.cbrt(8.0)); // 2.0
:
Użyteczne składowe klasy Math
metoda:
static double ceil(double a);
obliczenie zaokrąglonej w górę wartości argumentu
(dokładnie: najmniejsza wartość całkowita, większa lub równa
argumentowi)
przykład:
:
System.out.println(Math.ceil(Math.PI)); // 4.0
:
Użyteczne składowe klasy Math
metoda:
static double cos(double a);
podaje wartość funkcji
cos(a)
uwaga!
a
jest miarą kąta wyrażoną w radianach!
przykład:
:
System.out.println(Math.cos(0.0)); // 1.0
:
Użyteczne składowe klasy Math
metoda:
static double exp(double a);
obliczenie wartości
e
a
przykład:
:
System.out.println(Math.exp(0.0)); // 1.0
:
Użyteczne składowe klasy Math
metoda:
static double floor(double a);
obliczenie zaokrąglonej w dół wartości argumentu
(dokładnie: największa wartość całkowita, mniejsza lub równa
argumentowi)
przykład:
:
System.out.println(Math.floor(Math.PI)); // 3.0
:
Użyteczne składowe klasy Math
metoda:
static double hypot
(double a, double b);
obliczenie pierwiastka kwadratowego z wyrażenia
(a
2
+ b
2
)
przykład:
:
System.out.println(Math.hypot(3.0, 4.0)); // 5.0
:
Użyteczne składowe klasy Math
metoda:
static double log(double a);
obliczenie wartości
ln a
przykład:
:
System.out.println(Math.log(Math.E)); // 1.0
:
Użyteczne składowe klasy Math
metoda:
static double log10(double a);
obliczenie wartości
log a
przykład:
:
System.out.println(Math.log(100.0)); // 2.0
:
Użyteczne składowe klasy Math
metoda:
static double max(double a, double b);
static float max(float a, float b);
static int max(int a, int b);
static long max(long a, long b);
podaje większą z wartości
a
i
b
przykład:
:
System.out.println(Math.max(100.0, 200.0)); // 200.0
:
Użyteczne składowe klasy Math
metoda:
static double min(double a, double b);
static float min(float a, float b);
static int min(int a, int b);
static long min(long a, long b);
podaje mniejszą z wartości
a
i
b
przykład:
:
System.out.println(Math.min(100.0, 200.0)); // 100.0
:
Użyteczne składowe klasy Math
metoda:
static double pow(double a, double b);
oblicza wartość
a
b
przykład:
:
System.out.println(Math.pow(2.0, 3.0)); // 8.0
:
Użyteczne składowe klasy Math
metoda:
static double random();
podaje wartość pseudolosową
x
taką, że
0 ≤ x < 1
przykład:
:
System.out.println(Math.random()); // ???
:
Użyteczne składowe klasy Math
metoda:
static double rint(double a);
podaje wartość całkowitą (ale w typie double!)
najbliższą wartości a
przykład:
:
System.out.println(Math.rint(1.5)); // 2.0
:
Użyteczne składowe klasy Math
metoda:
static long round(double a);
podaje wartość całkowitą (w typie long!) najbliższą
wartości a
przykład:
:
System.out.println(Math.round(1.5)); // 2
:
Użyteczne składowe klasy Math
metoda:
static double signum(double a);
static float signum(float a);
podaje wartość funkcji
sgn a
przykład:
:
System.out.println(Math.round(-1.5)); // -1.0
:
Użyteczne składowe klasy Math
metoda:
static double sin(double a);
podaje wartość funkcji
sin a
uwaga!
a
jest miarą kąta wyrażoną w radianach!
przykład:
:
System.out.println(Math.sin(Math.PI / 2.0)); // 1.0
:
Użyteczne składowe klasy Math
metoda:
static double sqrt(double a);
podaje wartość pierwiastka kwadratowego z
a
przykład:
:
System.out.println(Math.sqrt(100.0)); // 10.0
:
Użyteczne składowe klasy Math
metoda
:
static double tan(double a);
podaje wartość funkcji
tg a
uwaga!
a
jest miarą kąta wyrażoną w radianach!
przykład:
:
System.out.println(Math.tan(Math.PI / 4.0));
// 0.99999999999999
:
Użyteczne składowe klasy Math
metoda:
static double toDegrees(double a);
przelicza miarę kąta a z radianów na stopnie
przykład:
:
System.out.println(Math.toDegrees(Math.PI)); // 180.0
:
Użyteczne składowe klasy Math
metoda:
static double toRadians(double a);
przelicza miarę kąta
a
podaną w stopniach na radiany
przykład:
:
System.out.println(Math.toDegrees(Math.PI)); // 180.0
:
Deklarowanie klas
Deklarując nową (własną) klasę należy
dostarczyć informacji o tym:
●
jak nazywa się nowa klasa (obowiązkowo)
●
jakie własności ma nowa klasa
(może nie mieć żadnych)
●
jakie metody ma nowa klasa
(może nie mieć żadnych)
Najprostsza mozliwa klasa...
...aczkolwiek o wątpliwej przydatności
praktycznej:
class Klasa { }
Najprostsza mozliwa klasa
class Klasa { }
Słowo kluczowe class otwiera deklarację nowej klasy
Najprostsza mozliwa klasa
class Klasa { }
Klasa jest identyfikatorem nowej klasy.
Nazwa klasy powinna zaczynać się wielką literą.
Najprostsza mozliwa klasa
class Klasa { }
Nawiasy { i } zawierają ciało deklaracji klasy.
Klasa
ma puste ciało deklaracji, tzn.
nie ma żadnego
składnika
– ani własności, ani metody.
Deklarujemy zmienną
obiekt,
która będzie przechowywać
obiekt klasy
Klasa
Wytworzenie obiektu klasy
class Klasa { }
class Main {
public static void main(String[] args) {
Klasa obiekt;
obiekt = new Klasa();
}
}
Fabrykujemy i podstawiamy pod zmienną
obiekt klasy
Klasa
Deklaracja nowej klasy
Klasa
Fabrykowanie i deklaracja
class Klasa { }
class Main {
public static void main(String[] args) {
Klasa obiekt = new Klasa();
}
}
Deklarujemy, fabrykujemy i podstawiamy obiekt klasy
Klasa
Czy można wypisać obiekt?
class Klasa { }
class Main {
public static void main(String[] args) {
Klasa obiekt = new Klasa();
System.out.println(obiekt);
}
}
Przekazujemy
obiekt
metodzie
println
– co się stanie?
Na standardowym wyjściu pojawi się napis np:
Klasa@42e816
Metoda toString
●
każda klasa
(nawet pusta) ma metodę toString
(na
razie przemilczymy przyczynę tego stanu rzeczy)
●
metoda toString jest niejawnie wywoływana z
obiektu zawsze wtedy, kiedy potrzebne jest
przekształcenie danych zawartych w obiekcie w
daną łańcuchową
●
domyślna metoda toString zwraca jako wynik
unikalny identyfikator obiektu używany wewnętrznie
przez JVM
●
definiując nową klasę, możemy podać własną
metodę toString, bardziej przystającą do naszych
potrzeb
Deklarowanie własności
●
teraz wyposażymy naszą nową klasę w kilka
własności
●
na początek zbadamy własności typów
podstawowych
●
zadeklarujemy po jednej własności typu int,
double, char i boolean
Deklarowanie własności
class Klasa {
int i;
double d;
char c;
boolean b;
}
class Main {
public static void main(String[] args) {
Klasa obiekt = new Klasa();
}
}
Jak widać,
deklarowanie własności w klasie
wygląda dokładnie tak samo, jak deklarowanie
zmiennych
Dostęp do własności obiektu uzyskujemy drogą
znanej już notacji kropkowej
Dostęp do własności
class Klasa {
int i;
double d;
char c;
boolean b;
}
class Main {
public static void main(String[] args) {
Klasa obiekt = new Klasa();
obiekt.i = 13;
System.out.println(obiekt.i);
}
}
Pamiętamy o tym, że własności
niestatyczne
istnieją
niezależnie w
każdym egzemplarzu
obiektu
(w każdej instancji klasy)
Dostęp do własności
class Klasa {
int i;
double d;
char c;
boolean b;
}
class Main {
public static void main(String[] args) {
Klasa obiekt1 = new Klasa(), obiekt2 = new Klasa();
obiekt1.i = 13;
obiekt2.i = 31;
System.out.println(obiekt1.i + ” ” + obiekt2.i);
}
}
Zbadamy, jakie wartości
początkowe są nadawane
własnościom niestatycznym
Wartości początkowe własności
class Klasa {
int i;
double d;
char c;
boolean b;
}
class Main {
public static void main(String[] args) {
Klasa obiekt = new Klasa();
System.out.println(”i = ” + obiekt.i);
System.out.println(”d = ” + obiekt.d);
System.out.println(”c = ” + obiekt.c);
System.out.println(”b = ” + obiekt.b);
}
}
Wartości początkowe własności
Oto wynik:
i = 0
d = 0.0
c =
b = false
Wniosek
Własności typów prostych
przybierają początkowe
wartości wywodzące się z
zera
byte, short, int, long 0
→
float, double 0.0
→
char '\u0000'
→
Boolean false
→
Na przykładzie obiektu klasy String
zbadamy teraz, jaka jest
początkowa wartość własności
obiektowych
Wartości początkowe własności
class Klasa {
int i;
double d;
char c;
boolean b;
String s;
}
class Main {
public static void main(String[] args) {
Klasa obiekt = new Klasa();
System.out.println(”s = ” + obiekt.s);
}
}
Wartości początkowe własności
Oto wynik:
s = null
Wniosek
Własności obiektowe przyjmują wartość
początkową
null
,
a więc
nie reprezentują żadnego obiektu
Deklarując własności klasy można
określić ich wartości początkowe.
W takim przypadku każdy sfabrykowany
obiekt klasy będzie miał własności
o wskazanych wartościach
Wartości początkowe własności
class Klasa {
int i = 1;
double d = 2.0;
char c = 'C';
boolean b = true;
String s = ”Hello”;
}
class Main {
public static void main(String[] args) {
Klasa obiekt = new Klasa();
System.out.println("i = " + obiekt.i);
System.out.println("d = " + obiekt.d);
System.out.println("c = " + obiekt.c);
System.out.println("b = " + obiekt.b);
System.out.println("s = " + obiekt.s);
}
}
Wartości początkowe własności
Oto wynik:
i = 1
i = 1
d = 2.0
c = C
b = true
s = Hello
Jeśli deklaracja pewnej własności
jest poprzedzona słowem static, to
będzie ona statyczna. Oznacza to, że
niezależnie od liczby sfabrykowanych
obiektów, taka własność istnieje
tylko w jednym egzemplarzu
.
Własności statyczne
class Klasa {
int i;
static int si;
}
class Main {
public static void main(String[] args) {
Klasa obiekt1 = new Klasa(), obiekt2 = new Klasa();
obiekt1.i++;
obiekt1.si++;
obiekt2.i++;
obiekt2.si ++;
System.out.println(obiekt1.i + ” ” + obiekt1.si);
System.out.println(obiekt2.i + ” ” + obiekt2.si);
}
}
Wartości początkowe własności
Oto wynik:
i = 1
1 2
1 2
Własności niestatyczne poddano inkrementacji
tylko raz – każdą z osobna
Własność statyczną poddano
inkrementacji dwukrotnie
Do własności statycznej
można odwoływać się również
poprzez nazwę klasy
(w wyniku wypisana zostanie liczba 2)
Własności statyczne
class Klasa {
int i;
static int si;
}
class Main {
public static void main(String[] args) {
Klasa obiekt1 = new Klasa(), obiekt2 = new Klasa();
obiekt1.i++;
obiekt1.si++;
obiekt2.i++;
obiekt2.si ++;
●
System.out.println(Klasa.si);
}
}
Własności statyczne
Uwaga!
statyczną własność klasy
nazywa się również
zmienną klasy
Deklarowanie metod
class Klasa {
int i;
int doKwadratu() {
return i * i;
}
}
class Main {
public static void main(String[] args) {
Klasa obiekt = new Klasa();
obiekt.i = 2;
System.out.println(obiekt.doKwadratu());
}
}
Metoda println
wypisze liczbę 4
Anatomia nagłówka metody
int dodaj(int i)
Określa, czy dana metoda zwraca wynik, a jeśli tak, to jaki:
●
void oznacza, że metoda nie zwraca żadnego wyniku i że wolno ją
wywoływać wyłącznie w tzw. pustym kontekście
●
nazwa typu prostego (np. int) oznacza, że metoda oblicza
wartość wskazanego typu; można ją wywoływać w kontekście
typu lub w kontekście pustym – w tym drugim przypadku
obliczona wartość zostanie odrzucona
●
nazwa klasy (np. String) oznacza, że dana metoda zwraca
referencję do obiektu wskazanej klasy; reguły wywoływania są
takie, jak dla typów prostych
Anatomia nagłówka metody
int dodaj(int i)
Nazwa metody, wybrana w taki sposób, aby jednoznacznie
manifestować czynność (bądź obliczenie) wykonywane przez metodę
Anatomia nagłówka metody
int dodaj(int i)
•
lista parametrów przekazywanych z zewnątrz do metody.
•
jeśli metoda nie oczekuje żadnych parametrów, to lista przyjmuje
postać () -
użycie słowa kluczowego
void
w tym kontekście
jest błędem!
•
jeśli metoda przyjmuje więcej niż jeden parametr, ich deklaracje
rozdziela się je przecinkami, np.
(int a, int b)
Kontekst wywołania
class Klasa {
void pusta() {
System.out.println(”pusta”);
}
int calkowita() {
System.out.println(”calkowita”);
return 1;
}
}
:
:
Klasa ob = new Klasa();
int zmienna;
zmienna = ob.calkowita();
ob.calkowita();
ob.pusta();
zmienna = ob.pusta();
ŹLE!
Co może metoda?
●
metoda może korzystać z
własności klasy
, w której
jest zadeklarowana, i może to czynić bez stosowania
notacji kropkowej (kwalifikowanej).
●
jeśli z jakichś powodów skorzystanie z notacji
niekwalifikowanej prowadzi do konfliktu nazw
wewnątrz metody, zaleca się korzystanie z notacji
kwalifikowanej, ale...
●
...rodzi to ważki problem – jak odwołać się do
własności obiektu, jeśli się nie wie, jak nazywa się ów
obiekt?
●
niejednoznaczność tę rozstrzyga się w taki sposób, iż
wprowadza się specjalne słowo kluczowe this –
oznacza ono zawsze ten obiekt, na rzecz którego
wywołano metodę.
Przykład
class Klasa {
int a, b;
int podajSumę() {
return a + b;
}
}
Metoda podajSumę odwołuje się do własności a i b klasy
Klasa – takie odwołanie może być niekwalifikowane (bez
użycia notacji kropkowej).
Przykład
class Klasa {
int a, b;
int podajSumę() {
return a + b;
}
}
class Main {
public static void main(String[] args) {
Klasa ob = new Klasa();
ob.a = 10;
ob.b = 22;
int zm = ob.podajSumę();
System.out.println(zm); // 32
}
}
Przykład
class Klasa {
int a;
void dodaj(int a) {
this.a += a;
}
}
Widzimy tutaj przykład tzw.
kolizji nazw
, która
powoduje niejednoznaczność – nie wiadomo, czy
a odnosi się do nazwy parametru, czy do nazwy
własności.
W Javie przyjęto następujące rozstrzygnięcie:
●
nazwa parametru (jako bardziej lokalna)
przesłania
nazwę własności – tym samym
nazwa a przestaje w tym kontekście oznaczać
własność
●
aby odzyskać dostęp do własności a, należy
posłużyć się
kwalifikacją
względem obiektu
o nazwie this
Przykład
class Klasa {
int a;
void dodaj(int a) {
this.a += a;
}
}
class Main {
public static void main(String[] args) {
Klasa ob = new Klasa();
ob.a = 10;
ob.dodaj(11);
System.out.println(ob.a); // 21
}
}
Metody statyczne
Tak jak własności,
metody również mogą być deklarowane jako
statyczne
– pociąga to za sobą istotne konsekwencje:
➔
metoda statyczna może zostać wywołana także wtedy, kiedy nie
istnieje żaden obiekt klasy – oznacza to, że
metodzie statycznej nie
wolno uzyskiwać dostępu do własności niestatycznych
➔
z tego samego powodu
metodzie statycznej nie wolno wywoływać
metod niestatycznych
●
z oczywistych powodów powyższe ograniczenia nie działaja w
drugą stronę, a więc:
➔
metoda niestatyczna może wywoływać metodę statyczną
(bo ta
druga istnieje zawsze)
➔
metoda niestatyczna może używać statycznych własności
(z tych
samych powodów)
Przykład
class Klasa {
int a;
static int sa;
void metoda() {
a++;
sa++;
}
static void smetoda() {
a++;
as++;
}
}
Metoda niestatyczna korzysta z
niestatycznej własności
DOBRZE
Metoda niestatyczna korzysta ze
statycznej własności
DOBRZE
Metoda statyczna korzysta z
niestatycznej własności
ŹLE
Metoda statyczna korzysta ze statycznej
własności
DOBRZE
Przykład
class Klasa {
void metoda1() {
}
void metoda2() {
metoda1();
smetoda1();
}
static void smetoda1() {
}
static void smetoda2() {
metoda1();
smetoda1();
}
}
Metoda niestatyczna woła metodę
niestatyczną
DOBRZE
Metoda niestatyczna woła metodę
statyczną
DOBRZE
Metoda statyczna woła metodę
niestatyczną
ŹLE
Metoda statyczna woła metodę
statyczną
DOBRZE
Zagadnienie projektowe
Wyobraźmy sobie następujący problem:
➔
chcemy skonstruować klasę, która pozwoli nam na wygodne i
bezpieczne operowanie datami
➔
taka klasa powinna przechowywać w sobie konkretną datę oraz
zawierać zestaw metod służących do wykonywania pożytecznych
operacji np. obliczania liczby dni pomiędzy dwoma datami
➔
zakładamy, że mechanizmy udostępniane przez tę klasę są
maksymalnie bezpieczne, tzn. klasa nie wyrazi zgody na to, aby
używać jej w nieprawidłowy sposób, np. dla zapamiętania daty
30 lutego 2000 roku
➔
wstępnie ustalamy, jakie dane powinna przechowywać klasa i
dochodzimy do wniosku, że są to:
rok
- typu int
miesiąc
-
typu int
dzień
-
typu int
Klasa 'Data' – pierwszy prototyp
class Data {
int
rok;
int
miesiąc;
int
dzień;
}
Na razie nasza klasa składa się tylko z własności i wyraźnie cierpi
na brak jakichkolwiek metod. W takiej wersji klasa wyraźnie
przypomina zwykłą strukturę, jaką znamy z języka „C”. Użycie
takiej klasy pozwala na spójne reprezentowanie i przechowywanie
dat, ale poza tym pożytek z niej nie jest imponujący.
Klasa 'Data' w użyciu
class Data {
int
rok;
int
miesiąc;
int
dzień;
}
class Main {
public static void main(String[] args) {
Data nowyrok = new Data();
nowyrok.rok = 2009;
nowyrok.miesiąc = 1;
nowyrok.dzień = 1;
}
}
Klasa 'Data'
:
:
System.out.println(nowyrok.dzień + ”/” +
nowyrok.miesiąc + ”/” + nowyrok.rok);
:
:
Wyobraźmy sobie teraz, że chcielibyśmy dysponować wygodnym
sposobem wypisywania naszej daty w czytelny i elegancki sposób.
Można to oczywiście zrobić tak jak poniżej, ale nie wydaje się, aby
było to rozwiązanie budzące entuzjazm programisty...
Klasa 'Data'
:
:
System.out.println(nowyrok);
:
:
O ileż piękniej byłoby, gdyby można się było posłużyć takim
eleganckim skrótem myślowym. My przekazujemy metodzie
println() obiekt klasy Data, a obiekt sam już wie, jaką przybrać
postać.
Co jest potrzebne, aby to marzenie stało się faktem?
Potrzebna jest metoda „toString”!
Klasa 'Data' – drugi prototyp
class Data {
int
rok;
int
miesiąc;
int
dzień;
public String toString() {
return dzień + ”/” + miesiąc + ”/” + rok;
}
}
Dopisujemy do naszej klasy metodę toString, dbając o to, aby jej
nagłówek wyglądał dokładnie tak, jak w tym przykładzie.
Niebawem wyjaśnimy, czemu jest to niezbędnie konieczne.
Oczywiście, możemy tu zawrzeć dowolny, wybrany przez nas,
sposób kodowania daty.
Klasa 'Data' w użyciu
class Data {
int
rok;
int
miesiąc;
int
dzień;
public String toString() {
return dzień + ”/” + miesiąc + ”/” rok;
}
}
class Main {
public static void main(String[] args) {
Data nowyrok = new Data();
nowyrok.rok = 2009;
nowyrok.miesiąc = 1;
nowyrok.dzień = 1;
System.out.println(nowyrok);
}
}
Klasa 'Data' i nadużycie
class Main {
public static void main(String[] args) {
Data dziwna = new Data();
dziwna.rok = 2009;
dziwna.miesiąc = 13;
dziwna.dzień = 1;
System.out.println(nowyrok);
}
}
Niestety, nasza klasa jest
zupełnie bezbronna wobec
takich oto nadużyć.
Jak temu zaradzić?
Wyobraźmy sobie, że istnieje
mechanizm, który wyklucza
możliwość manipulowania
własnością klasy poza naszą
wiedzą. Dzięki niemu
uzyskujemy pełną kontrolę
na tym, jak manipuluje się
wartością własności.
Taki mechanizm nazywa się
metodami dostępowymi
.
Klasa 'Data' – trzeci prototyp
class Data {
int
rok;
int
miesiąc;
int
dzień;
void setMiesiąc(int miesiąc) {
if(miesiąc < 1 || miesiąc > 12)
System.out.println(”No chyba na głowę upadłeś!”);
else
this.miesiąc = miesiąc;
}
}
Metoda dostępowa, której zadaniem jest wpisywanie wartości
do pewnej własności jest nazywana
setterem
, a jej nazwa
powstaje ze sklejenia słowa „set” (ustaw) i nazwy ustawianej
własności
(z uwzględnieniem konwencji dotyczącej wielkości liter)
Klasa 'Data' – trzeci prototyp
class Data {
int
rok;
int
miesiąc;
int
dzień;
int getMiesiąc() {
System.out.println(”Jakiż to piękny miesiąc...”);
return miesiąc;
}
}
Metoda dostępowa, której zadaniem jest oczytywanie wartości
pewnej własności jest nazywana
getterem
, a jej nazwa powstaje
ze sklejenia słowa „get” (weź) i nazwy odczytywamek własności
(z uwzględnieniem konwencji dotyczącej wielkości liter)
Klasa 'Data' użyta bezpiecznie
class Main {
public static void main(String[] args) {
Data dziwna = new Data();
dziwna.rok = 2009;
dziwna.setMiesiąc(1);
dziwna.setMiesiąc(13);
dziwna.miesiac = 13;
dziwna.dzień = 1;
System.out.println(nowyrok);
}
}
Takie postępowanie zostanie
przez obiekt zaakceptowane
Na to nasz obiekt nie
pozwoli
Z żalem stwierdzamy, że to
się – niestety - powiedzie... :(
Pytanie
Pytanie
:
Czy można sprawić, aby pewna własność była dostępna tylko i
wyłącznie poprzez metody dostępowe i aby była ukryta przed
oczyma użytkowników klasy?
Odpowiedź
:
Tak, to możliwe. Należy uczynić taką własność
własnością prywatną
.
Teraz własność miesiąc jest
własnością
prywatną
, co
oznacza, że nie wolno odwołać
się do niej poprzez jej nazwę –
taka własność staje się
niewidoczna z zewnątrz klasy.
Klasa 'Data' – czwarty prototyp
class Data {
int
rok;
private int
miesiąc;
int
dzień;
int getMiesiąc() {
return miesiąc;
}
void setMiesiąc(int miesiąc) {
if(miesiąc < 1 || miesiąc > 12)
System.out.println(”Nic z tego!”);
else
this.miesiąc = miesiąc;
}
public String toString() {
return rok + ”/” + miesiąc + ”/” + dzień;
}
}
Takie odwołanie jest poprawne.
Własność rok nie jest prywatna
Klasa 'Data' z własnością prywatną
class Data {
:
:
:
:
}
class Main {
public static void main(String[] args) {
Data nowyrok = new Data();
nowyrok.rok = 2009;
nowyrok.miesiąc = 1;
}
}
Takie odwołanie jest niepoprawne.
Własność miesiąc jest prywatna.
Kompilator zgłosi błąd!
Podsumujmy
Jeżeli deklaracja pewnej własności jest poprzedzona poprzedzona
słowem kluczowym private, oznacza to, że własność ta deklarowana
jest jako
prywatna
.
Bezpośredni dostęp do
własności prywatnej
(„dostęp
po nazwie
”)
możliwy jest tylko i wyłącznie z wnętrza klasy – próba dostania się do
niej z innego miejsca wywoła błąd kompilacji.
Możliwy jest jednak dostęp z użyciem metod dostępowych (
getter
i
setter
), które dodatkowo pozwalają uzyskać kontrolę na procesem
modyfikowania i odczytywania wartości własności.
Jako
prywatna
może być także zadeklarowana dowolna metoda
klasy.