Marzec
22
2009

Pola czy właściwości?

Słowa kluczowe: , , | Kategorie: Programowanie
No Gravatar

Pole klasy to zmienna zdefiniowana wewnątrz klasy. Właściwość (ang. property) to wartość, na której operuje jedna lub dwie spośród metod:

Type getXXX()
metoda pobierająca wartość właściwości (ang. getter),
void setXXX(Type value)
metoda ustawiająca wartość właściwości (ang. setter).

Obie metody posiadają ten sam człon XXX – nazwę właściwości. Również typ właściwości (Type) jest w obu przypadkach ten sam.

Poniżej znajduje się przykład pola:

public Integer value;

Właściwość spełniająca tę samą funkcjonalność będzie wyglądać tak:

private Integer value;

public Integer getValue() {
    return this.value;
}

public void setValue(Integer value) {
    this.value = value;
}

Ale po co w ogóle korzystać z właściwości, skoro zdefiniowanie pola jest dużo szybsze? Co zyskujemy definiując dwie dodatkowe metody?

Po pierwsze można w ten sposób zdefiniować właściwość tylko do odczytu. Wystarczy, że setter nie będzie istniał. Może to być potrzebne w sytuacji, gdy wartość ustawiana jest tylko w konstruktorze albo innych metodach klasy. Analogicznie definiuje się właściwości tylko do zapisu.

Często dostęp do zapisu i odczytu właściwości mają różną widoczność. Na przykład setter chroniony (protected) będzie mógł zostać wywołany poza pakietem jedynie przez klasy potomne. Natomiast domyślna widoczność ograniczy ustawianie wartości jedynie do pakietu, w którym znajduje się klasa.

Ważnym powodem do stosowania właściwości jest potrzeba operowania na wartościach, które nie są przechowywane w polach klasy. Najprostszym przykładem może być hasło:

@Column(name = "password")
private String password;

private String getPassword() {
    return decrypt(hexToBytes(this.password));
}

public void setPassword(String password) {
    this.password = bytesToHex(encrypt(password));
}

boolean isPassword(String password) {
    return this.getPassword().equals(password);
}

W powyższym przykładzie kolumna bazy danych, przechowująca szesnastkowy zapis zaszyfrowanego hasła, mapowana jest na prywatne pole klasy encji. Istnieje jednak właściwość operująca na haśle zapisanym jawnym tekstem – dostępna do odczytu tylko dla składowych klasy. Metody encrypt, decrypt, bytesToHex oraz hexToBytes zdefiniowane są gdzieś wewnątrz klasy.

Podobnie jest z długością okręgu:

private Double radius;

public Double getLength() {
    return this.radius * 2.0 * Math.PI;
}

public void setLength(Double length) {
    this.radius = length / 2.0 / Math.PI;
}

Pole przechowuje jedynie promień okręgu, natomiast jego obwód obsługiwany jest poprzez właściwość.

Inną sytuacją, wymagającą użycia właściwości, jest powiadamianie obserwatorów o zmianie wartości. Wówczas to właśnie setter jest miejscem, w którym dochodzi do przeprowadzenia tej dodatkowej operacji.

Co prawda w najprostrzych przypadkach można obejść się bez właściwości, lecz warto je stosować nawet wówczas. Pozwoli to w razie potrzeby obejść się bez szerokiego refaktoringu, mającego na celu dostosowanie kodu aplikacji opartego na dostępie do pól do obsługi właściwości.

Napisz Komentarz

*