Viditelnost privatnej premennej v Jave

fero

Viditelnost privatnej premennej v Jave
« kdy: 06. 03. 2012, 21:40:16 »
zdravim, ja neviem ci nieco naozaj podstatne nechapem, ale takato vec ma trapi.

mam v jave classu A ktora ma privatny atribut id. overridnem equals(), vygenerovany equals v netbeansoch vyzera takto napr.

Kód: [Vybrat]
    @Override
    public boolean equals(Object obj) {
if (obj == null) {
    return false;
}
if (getClass() != obj.getClass()) {
    return false;
}

A other = (A) obj;
if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) {
    return false;
}
return true;
    }

No, a ja nechapem, ako je mozne, ze funguje taka vec ako other.id. ved ten atribut id je privatny pre ten objekt, tak preco je viditelny? aky ma potom rozdiel pouzivat defaultny getter? ja by som pouzival prave nieco ako this.id.equals(other.getId()) co sa mi zda prirodzene lebo id je privat, ale tu to zazracne funguje ... nestacim sa cudovat :D
« Poslední změna: 07. 03. 2012, 09:56:37 od Petr Krčmář »


Dan

Re:viditelnost privatnej premennej v jave
« Odpověď #1 kdy: 06. 03. 2012, 22:09:08 »
Proměnná je privátní vzhledem ke třídě, né k objektu.

gazda

Re:viditelnost privatnej premennej v jave
« Odpověď #2 kdy: 07. 03. 2012, 08:32:53 »
Proměnná je privátní vzhledem ke třídě, né k objektu.
Ono platí ešte silnejšie tvrdenie: Hranice privátnosti sú dané zdrojovým súborom .java.
Aj nasledujúci kód funguje:
Kód: [Vybrat]
public class ClassA {

private static class InnerA {
private int i;
}

public ClassA() {
InnerA a = new InnerA();

/* the following would not work if InnerA was declared in its own java file. */
a.i = 0;
}
}

Natix

Re:Viditelnost privatnej premennej v Jave
« Odpověď #3 kdy: 07. 03. 2012, 19:41:41 »
gazda:
To není tak docela pravda. Vnitřní a top level třída sice dokážou pomocí metod vygenerovaných kompilátorem vzájemně vidět na svoje private metody a fieldy, ale pokud deklaruju v jednom .java souboru jednu public a jednu package private třídu, tak mezi nimi už to neplatí.

soubor Main.java:
Kód: [Vybrat]
public class Main {

private static final int CONSTANT = 5;

public static void main(String... args) {
System.out.println(Something.method());  // není vidět
}

}

class Something {

private static int method() {
return Main.CONSTANT; // není vidět
}

}

Mitch

Re:Viditelnost privatnej premennej v Jave
« Odpověď #4 kdy: 07. 03. 2012, 21:09:48 »
aky ma potom rozdiel pouzivat defaultny getter?

Používat gettery má význam v případě, že používáš třeba nějaký ORM framework a tvá třída má některé své atributy jako lazy-load. Pak, pokud by jsi přistupoval přímo k proměnným, tak ORM framework nezjistí že má načíst odpovídající hodnotu z DB a ty dostaneš null. (Ono totiž ve skutečnosti nemáš referenci na objekt té třídy, ale jen na nějakou zástupnou proxy, která data načítá po zavolání příslušného getteru. Tam je pak opravdu nutné používat gettery. Ale jinak je si myslím v pořádku přistupovat k proměnným přímo.


Kit

Re:Viditelnost privatnej premennej v Jave
« Odpověď #5 kdy: 07. 03. 2012, 21:17:46 »
aky ma potom rozdiel pouzivat defaultny getter?

Používat gettery má význam v případě, že používáš třeba nějaký ORM framework a tvá třída má některé své atributy jako lazy-load. Pak, pokud by jsi přistupoval přímo k proměnným, tak ORM framework nezjistí že má načíst odpovídající hodnotu z DB a ty dostaneš null. (Ono totiž ve skutečnosti nemáš referenci na objekt té třídy, ale jen na nějakou zástupnou proxy, která data načítá po zavolání příslušného getteru. Tam je pak opravdu nutné používat gettery. Ale jinak je si myslím v pořádku přistupovat k proměnným přímo.

Konečně někdo popsal, jak se mají gettery a settery používat. Dlouho jsem nemohl přijít na to, k čemu jsou dobré. Primitivní gettery a settery slouží jen k likvidaci výkonu procesoru, ale zmíněné důvody považuji za legitimní.

Mitch

Re:Viditelnost privatnej premennej v Jave
« Odpověď #6 kdy: 07. 03. 2012, 22:01:03 »
Konečně někdo popsal, jak se mají gettery a settery používat. Dlouho jsem nemohl přijít na to, k čemu jsou dobré. Primitivní gettery a settery slouží jen k likvidaci výkonu procesoru, ale zmíněné důvody považuji za legitimní.

Ono já bych ty gettery a settery tak nezatracoval. Ono to z mého příspěvku nebylo asi úplně jasné, ale ten přímí přístup k proměnným jsem měl namysli pouze v případě implementace metod hasCode, equals a jim podobné. Tam programátor ví, jaká je struktura té třídy a zda si může dovolit přistupovat k proměnným přímo. To samé platí o vnořených třídách. Ale používat přímí přístup obecně mě nepřijde jako dobrý nápad. Ukazuje se tím příliš mnoho implementačních detailů a snižuje se tím možnost dalších úprav čí výměna jednotlivých tříd. Protože co v jedné implementaci může být přímo atribut se může v jiné implementaci klidně dopočítávat za běhu. Pokud použijete gettery a settery, můžete jednotlivé implementace tříd zaměňovat a program bude fungovat bez problému dále. To vše samozřejmě úzce souvisí i s programováním oproti rozhraním, ale to už bych utíkal od tématu.

Nicméně, jakožto programátor pro platformu Android uznávám, že někdy se tyto výhody přístupu přes gettery/settery porušují z výkonnostních důvodů. To platí tedy hlavně pro mobilní platformy. U webových či desktopových aplikacích je tento argument lichý.

Kit

Re:Viditelnost privatnej premennej v Jave
« Odpověď #7 kdy: 07. 03. 2012, 23:54:56 »
... Ale používat přímí přístup obecně mě nepřijde jako dobrý nápad.

To jsem rozhodně neměl na mysli. K proměnným objektu se nesnažím přistupovat přímo ani prostřednictvím getteru či setteru. Snažím se, aby objekt něco dělal. Místo setteru dělám controller, místo getteru viewer.

kuka

Re:Viditelnost privatnej premennej v Jave
« Odpověď #8 kdy: 08. 03. 2012, 11:14:19 »
Umozneni primeho pristupu k promennym porusuje koncept zapouzdreni. Proto muze byt v poradku v ramci jedne tridy (nebo treba i package), ale nikoliv obecne. Nelze pak zarucit vnitrni konzistenci, nelze dostat kontraktu metod, implemetacni detaily se stavaji soucasti rozhrani. Ne vzdy to musi vadit, rada trid napriklad slouzi pouze jako analogie recordu a nema zadnou vnitrni logiku.

Mitch

Re:Viditelnost privatnej premennej v Jave
« Odpověď #9 kdy: 08. 03. 2012, 14:43:23 »
Místo setteru dělám controller, místo getteru viewer.
Tak z toho moc moudrý nejsem. Mohl by jsi to prosím trochu rozvést? S konceptem controlleru a view (architektura MVC) seznámen jsem, ale v kontextu jedné třídy mi to nic neříká.

Umozneni primeho pristupu k promennym porusuje koncept zapouzdreni. Proto muze byt v poradku v ramci jedne tridy (nebo treba i package), ale nikoliv obecne. Nelze pak zarucit vnitrni konzistenci, nelze dostat kontraktu metod, implemetacni detaily se stavaji soucasti rozhrani. Ne vzdy to musi vadit, rada trid napriklad slouzi pouze jako analogie recordu a nema zadnou vnitrni logiku.
Úplný souhlas.

Kit

Re:Viditelnost privatnej premennej v Jave
« Odpověď #10 kdy: 08. 03. 2012, 16:34:36 »
Místo setteru dělám controller, místo getteru viewer.
Tak z toho moc moudrý nejsem. Mohl by jsi to prosím trochu rozvést? S konceptem controlleru a view (architektura MVC) seznámen jsem, ale v kontextu jedné třídy mi to nic neříká.

Jak už jsem psal, do vnitřních proměnných z vnějšku nelezu. Bylo by to proti koncepci OOP. Zbývají veřejné (resp. protected) metody. Podle mne je velkou chybou, pokud tato metoda je jednořádková a vrací pouze jeden údaj. Vždycky totiž ten údaj chci s něčím zkompletovat nebo ho použít k nějakému rozhodování. A tyto operace vložím do metody toho objektu. Metoda mi pak z objektu nevrací elementární údaj, ale zpracovaná data.

Například při výpočtu vzdálenosti od referenčního bodu nedělám:
Kód: [Vybrat]
x=objekt.getX()-x0;
y=objekt.getY()-y0;
vzdalenost=Math.sqrt(x*x+y*y);
ale svěřím to metodě, kterou mám v objektu a která má k těmto proměnným přístup:
Kód: [Vybrat]
vzdalenost=objekt.vzdalenost(x0,y0);

Místo dvou getterů mám tedy jeden viewer, který mi poskytne požadovaná data.

Je to jen příklad, který mě zrovna napadl a jehož princip je snad jasný. Přikázal jsem objektu, aby mi řekl, jak je od souřadnic (x0,y0) daleko. Nesahám na vnitřní proměnné a nepoužívám primitivní getter. Samozřejmě je vhodnější s dvojicí (x,y) pracovat jako s objektem, strukturou nebo třeba komplexním číslem. Je to jen příklad.

Podobně místo primitivního setteru zavolám metodu, které předám nezpracovaná a neošetřená data, se kterými si musí nějak poradit, uložit do takového schématu, jaký potřebuje a vrátit status. Také může požadovanou operaci odmítnout (např. vyhodit výjimku), záleží to jen na něm. Tím se z obyčejného setteru stane controller.

Architektura MVC nemusí být jen mezi objekty, ale může být i uvnitř objektu mezi metodami a datovými strukturami.

Mitch

Re:Viditelnost privatnej premennej v Jave
« Odpověď #11 kdy: 08. 03. 2012, 18:18:02 »
Tak zase jsem o něco chytřejší, alespoň co se týče názvosloví. :-) U nás se tomuhle říká prostě Bussines Logic a většina tříd by jí samozřejmě měla mít. Jinak by to byly jen nositelé dat bez vlastního chování, což je také proti principům OOP. Ale i přesto si myslím, že se člověk používání prostých (jednořádkových) přístupových metod nevyhne. Pokud budeš vyvíjet nějakou Enterprise aplikaci a používat třeba Spring Framework, tak ten to přímo podmiňuje. Jasně, settery můžou provádět nějakou kontrolu vstupních dat, to určitě, ale o to teď nejde. Také pokud budu chtít ve view zobrazit reprezentaci daného objektu, použití hloupých getterů se také nevyhnu.

Kit

Re:Viditelnost privatnej premennej v Jave
« Odpověď #12 kdy: 08. 03. 2012, 20:18:26 »
Jasně, settery můžou provádět nějakou kontrolu vstupních dat, to určitě, ale o to teď nejde. Také pokud budu chtít ve view zobrazit reprezentaci daného objektu, použití hloupých getterů se také nevyhnu.

Pokud budu chtít zobrazit reprezentaci daného objektu, napíši pro něj další viewer (metodu, která mi zkompletuje požadovaná data) a vyhnu se tak hloupým getterům. Pokud budu ukládat vstupní data, tak málokdy budu ukládat jen jeden údaj, ale budu jich voláním jedné metody ukládat celou sadu. To už také nemusí být primitivní setter. Často mi tuto roli zastává už konstruktor s více parametry.

Bussines Logic bude zřejmě to správné označení, ale principy jsou de facto stejné jako v MVC: Divide et impera.