[Java] Waarom data hiding (of waarom juist niet?)

Pagina: 1
Acties:

  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Hallo geachte medetweakers,

ik krijg in voorbereiding van het HBO Informatica een inleiding in Java-programmeren, en daarbij komt de volgende vraag in me boven:

Stel je voor dat je een klasse schrijft van een artikel. Zo'n artikel heeft een aantal variabelen zoals artikelnummer, omschrijving enz. Nou zijn er imho 2 manieren om de klasse te implementeren:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Artikel {
   private String artCode;
   private String omschrijving;

   // CONSTRUCTOR
   public Artikel(String code, String oms) {
      this.artCode = code;
      this.omschrijving = oms;
   }

   public String getArtCode() {
      return artCode;
   }

   public String getOmschrijving() {
      return omschrijving;
   }
}


OF:

Java:
1
2
3
4
5
6
7
8
9
public class Artikel {
   public String artCode;
   public String omschrijving;

   public Artikel(String code, String oms) {
      this.artCode = code;
      this.omschrijving = oms;
   }
}


waarbij je dus in het eerste geval kiest voor data hiding. Wat ik me dus afvraag is: wat voor voordelen heeft de data hiding nou boven het public declareren van de variabelen?

Misschien heeft iemand van jullie hier een heldere kijk op waarvoor alvast dank :)

  • whoami
  • Registratie: December 2000
  • Laatst online: 10:59
In sommige gevallen wil je niet dat iedereen zomaar aan jouw variablen kan.
Meestal wil je dat dmv een 'gecontroleerde' weg laten gaan.

Van sommige members wil je bv wel dat men ze kan uitlezen, maar niet dat men ze kan wijzigen.

https://fgheysels.github.io/


  • JaWi
  • Registratie: Maart 2003
  • Laatst online: 14-01 21:58

JaWi

maak het maar stuk hoor...

Wat mij betreft kun je het beste voor de data-hiding variant gaan:
  • Het maakt erg expliciet wat wel en wat niet toegankelijk is voor de gebruikers van dit object;
  • Het zorgt voor een scheiding tussen de specificatie van je klasse en de implementatie van je klasse;
  • Het stelt je in staat om een betere voorspelling te doen van de toestand waarin een object-instantie zich kan bevinden (bij publieke velden kunnen deze op meerdere plekken van je applicatie direct gewijzigd worden, zonder dat je daar direct weet van hebt);

Statistics are like bikinis. What they reveal is suggestive, but what they hide is vital.


  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Kijk, daar kan ik wat mee :*). Met data-hiding heb ik dus duidelijk meer controle over m'n applicatie. Het zal dan ook minder foutgevoelig zijn. Bedankt! _/-\o_

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 11:51

Robtimus

me Robtimus no like you

Zelfs als je velden allemaal zowel een getter als een setter krijgen, dan is het nog niet verstandig om public te declareren.
Java:
1
2
3
4
public class Test
{
    public String string;
}
vs
Java:
1
2
3
4
5
6
public class Test
{
    private String string;
    public String getString() { return string; }
    public void setString(String s) { string = s; }
}
Mocht je later willen dat string bv geen null mag zijn, dan kun je daar in het eerste geval niets tegen doen. In het tweede kun je gewoon een check in de setter inbouwen, voor de buitenwereld verandert er bijna niets (alleen in het geval ze die setter aanroepen met een string die niet aan de check voldoet).

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • -FoX-
  • Registratie: Januari 2002
  • Niet online

-FoX-

Carpe Diem!

Stel dat je een FileUpload component geschreven hebt, die je later waarschijnlijk weer zou willen gebruiken en eventueel publiekelijk beschikbaar wil maken.

Dit is de interface die je dan bvb kan aanbieden
Java:
1
2
3
public interface FileManager {
  public uploadFileToServer(File file);
}

De implementatie ziet er bvb als volgt uit:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class FileManagerImpl implements FileManager {
  public uploadFileToServer(File file) {
    checkDiskSpace(file.size());
    validateFileExtension(file);
    File folder = generateUniqueFolder();
    // do actual upload in folder
  }

  private void checkDiskSpace(int fileSize) {
    // check if the file fits on the server, else throw Exception
  }

  private void validateFileExtension(File file) {
    // check if the file has a valid extention, else throw Exception
  }

  private File generateUniqueFolder() {
    // generate an unique folder for the file, so existing files wouldn't be overwritten
  }
}


Een gebruiker is alleen geïnteresseerd dat zijn file uiteindelijk op een correcte manier op de server terecht zal komen, wat hiervoor precies allemaal achter de schermen moet gebeuren maakt hem niets uit. Ook zou je niet willen dat een programmeur, nutteloze lege unieke folders gaat genereren. Vandaar dat je hem enkel de toegang geeft tot de uploadFileToServer methode.

  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Maar als je bijvoorbeeld in de klasse Integer van Java zelf kijkt, zie je dat daar public fields in staan (zoals MIN_VALUE en MAX_VALUE). Waarom zou dat dan niet in een getter zijn gestopt? Je kan hem toch read-only maken als je alleen een get gebruikt? Volgens mij bereik je dan hetzelfde.

edit:

reactie @IceManX

[ Voor 6% gewijzigd door coenbijlsma op 01-06-2005 13:12 ]


Verwijderd

cbijlsma schreef op woensdag 01 juni 2005 @ 13:11:
Maar als je bijvoorbeeld in de klasse Integer van Java zelf kijkt, zie je dat daar public fields in staan (zoals MIN_VALUE en MAX_VALUE). Waarom zou dat dan niet in een getter zijn gestopt? Je kan hem toch read-only maken als je alleen een get gebruikt? Volgens mij bereik je dan hetzelfde.

edit:

reactie @IceManX
Er is, vanuit wiskundig standpunt maar één getal met waarde MAX_VALUE / MIN_VALUE. Omdat een Integer-object toch readonly is (je kan de waarde van een integer niet veranderen, kijk maar eens naar de beschikbare methods), is het beter om voor deze speciale waarden een static variable aan te maken. Hierdoor voorkom je onnodig opnieuw en opnieuw en ... aanmaken van hetzelfde object.

Om dezelfde reden had men beter een Boolean.TRUE en een Boolean.FALSE ingevoerd, ipv. een constructor waarmee je de waarde aan mee geeft. Op die manier heb je doorheen je hele applicatie maar 2 immutable objecten (true en false), ook al gebruik je het op 1000 plaatsen.

daarbij:

code:
1
class Integer { public static Integer MAX_VALUE = new Integer(...); }

en
code:
1
2
3
4
class Integer {
   private static Integer MAX_VALUE = new Integer(...);
   public Integer getMaxValue() { return MAX_VALUE; }
}


is natuurlijk hetzelfde. (misschien gebeurt dat ondertussen al bij de Boolean-constructor, maar vroeger was het niet zo)

edit: zo te zien heeft Boolean wel een TRUE en FALSE field, en worden deze ook waarschijnlijk gebruikt in de constructor. Ik dacht dat dit vroeger niet was, en in de constructor telkens een nieuw object aangemaakt werd. Men had beter de constructor private gemaakt, maar omv. backwards compatibility gaat dat dus niet meer.

[ Voor 12% gewijzigd door Verwijderd op 01-06-2005 13:20 ]


Verwijderd

Er is geen interface te definieren over een attribuut, wel over methodes. Dus je moet ook altijd met de concrete klasse te maken hebben. (enkel aanvulling op het eerder vermelde, bij lange na niet het belangrijkste argument)

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 22-04 03:55

Nick_S

++?????++ Out of Cheese Error

Verwijderd schreef op woensdag 01 juni 2005 @ 13:17:

code:
1
2
3
4
class Integer {
   private static Integer MAX_VALUE = new Integer(...);
   public Integer getMaxValue() { return MAX_VALUE; }
}
Sterker nog, de variable MAX_VALUE is gedefinieerd als een final variabele, zodat deze na het eenmaal ingeladen zijn van de klasse Integer nooit meer gewijzigd kan worden. Dan is het ook niet nodig om hier later controle op uit voeren.

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Per saldo gebruik je data-hiding dus alleen niet als de waarde van de variabele niet meer gewijzigd wordt na het inladen van de klasse (dus final)? In de overige gevallen wil je dus controle hebben / heb je controle nodig en gebruik je methodes om de waarde van een variabele op te halen als ik het goed begrijp...

Verwijderd

Een klasse dat niks anders is dan een data contianer zou je voor performance redenen public attributen kunnen geven. Voorbeelden daarvan zijn de klassen Point en Dimension.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Verwijderd schreef op woensdag 01 juni 2005 @ 14:41:
Een klasse dat niks anders is dan een data contianer zou je voor performance redenen public attributen kunnen geven. Voorbeelden daarvan zijn de klassen Point en Dimension.
Getters/Setters voor simpele attributen zijn net zo snel als de attributen direct aan te spreken. De jit-compiler optimaliseerd de hele call erom weg.. de getter/setter wordt dan alleen gebruikt als compiletime veiligheid.

Verwijderd

Normaliter is het returnen van een primitieve by-value, hoe gaat JIT daar dan mee om?

Verwijderd

Verwijderd schreef op woensdag 01 juni 2005 @ 14:53:
Normaliter is het returnen van een primitieve by-value, hoe gaat JIT daar dan mee om?
Correctie:

Java werkt -altijd- by-value, ook voor objecten. Je hebt geen return by reference en ook geen pass-by-reference in java. In C++ heb je dit wel.

Vooral bij beginnende programmeurs of mensen die niet zo goed het verschil weten wordt altijd maar weer gedacht dat java wel pass-by-reference heeft. Echter, dit is niet waar.

  • JaWi
  • Registratie: Maart 2003
  • Laatst online: 14-01 21:58

JaWi

maak het maar stuk hoor...

Verwijderd schreef op woensdag 01 juni 2005 @ 15:02:
[...]
Java werkt -altijd- by-value, ook voor objecten. Je hebt geen return by reference en ook geen pass-by-reference in java. In C++ heb je dit wel.

Vooral bij beginnende programmeurs of mensen die niet zo goed het verschil weten wordt altijd maar weer gedacht dat java wel pass-by-reference heeft. Echter, dit is niet waar.
Drats, heeft "Big Blue" me weer voorgelogen (zie myth 3)... ;)

Statistics are like bikinis. What they reveal is suggestive, but what they hide is vital.


Verwijderd

Verwijderd schreef op woensdag 01 juni 2005 @ 15:02:
Correctie:
Java werkt -altijd- by-value, ook voor objecten. Je hebt geen return by reference en ook geen pass-by-reference in java. In C++ heb je dit wel.
Correctie:
primitieve gaan by-value, Objecten (waaronder dus arrays) by reference

Verwijderd

Verwijderd schreef op woensdag 01 juni 2005 @ 15:06:
[...]

Correctie:
primitieve gaan by-value, Objecten (waaronder dus arrays) by reference
Correctie:
1) Jij bent een beginnende programmeur

of

2) Jij bent dom

;)

Modbreak:Gemeend of niet, dit soort opmerkingen willen we hier niet zien. Trollen doe je maar ergens anders, niet op GoT.


Je hebt GEEN pass-by-refernce in java. Ik snap dat het moeilijk voor je is om te begrijpen, maar mischien dat het volgende voorbeeldje het verduidelijkt:

Java:
1
2
3
4
5
6
7
8
9
10
11
void foo( Integer x ) {
    x = new Integer(5);
}

void bar() {

   Integer y = new Integer(1);
   foo ( y );
   // Na deze call is y nog steeds het object met de 1 erin
   // Met call by reference had hetgeen y naar wijst gewijzigd kunnen worden
}

[ Voor 9% gewijzigd door NMe op 01-06-2005 15:44 ]


  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
Op die manier heb je feitelijk nooit call-by-reference; er wordt altijd een waarde op de stack gezet, welke nooit meer gebruikt wordt nadat de methode gereturned is.

Effectief heeft markvleth gewoon gelijk; wat er namelijk wordt doorgegeven bij een method-call met objecten als variabelen, zijn referenties naar objecten. Sterker nog; in Java werk je altijd via referenties naar objecten. Ik moet de eerste programmeur nog tegenkomen die in Java een object zelf by value weet mee te geven aan een methode...

Daarnaast vond ik jouw reply behoorlijk respectloos overkomen, m.a.w. een duidelijke flame

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


Verwijderd

Verwijderd schreef op woensdag 01 juni 2005 @ 15:18:
[...]

Je hebt GEEN pass-by-refernce in java. Ik snap dat het moeilijk voor je is om te begrijpen, maar mischien dat het volgende voorbeeldje het verduidelijkt:

Java:
1
2
3
4
5
6
7
8
9
10
11
void foo( Integer x ) {
    x = new Integer(5);
}

void bar() {

   Integer y = new Integer(1);
   foo ( y );
   // Na deze call is y nog steeds het object met de 1 erin
   // Met call by reference had hetgeen y naar wijst gewijzigd kunnen worden
}
Ok, ik snap iets niet helemaal geloof ik:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Test {
  public Test() {
    MyClass myClass = new MyClass(5);
    changeValue(myClass, 10);
    System.out.println("Value: "+myClass.getValue());
  }
  
  public void changeValue(MyClass myClass, int newValue){
    myClass.setValue(newValue);
  }

  public static void main(String[] args) {
    Test test = new Test();
  }
}

class MyClass{
  private int myValue = 0;
  
  public MyClass(int value){
    myValue = value;
  }
  
  public void setValue(int value){
    myValue = value;
  }
  
  public int getValue(){
    return myValue;
  }
}


resultaat:
Value: 10
Als Java geen pass by reference heeft, zou het toch resultaat 5 moeten zijn :?

  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
Precies! (aangezien er anders een copy van myClass op de stack gezet zou worden).
Maar dat is dus niet zo, er wordt een copy van de referentie naar myClass op de stack gezet, waardoor in de methode changeValue er (via die reference) dus gewoon met hetzelfde object wordt gewerkt als waar de varaiable myClass in methode Test() naar wijst.

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

't Belangrijkste (en enige?) verschil met pass by reference is vziw dat als je een reference null maakt, de originele waarde dat ook is. Bij Java is dat niet het geval. In Java heet het overigens ook geen pass by reference, hoewel het het natuurlijk wel heel dicht benaderd.

Overigens zijn er nog wel wat redenen waarom het beter is om niet direct de properties te benaderen. Bijvoorbeeld omdat er dan niet (zo makkelijk) een proxy (on-the-fly) gegenereerd kan worden zoals voor bijvoorbeeld Hibernate nodig is. Je kan ook geen synchronizatie inbouwen, behalve door de property zelf synchronized te maken. En meer van dat soort dingen.

Variabelen zoals die MAX_VALUE worden overigens vaak "constanten" genoemd en die zijn bedoeld als manier om vaste waarden door te geven en evt bekend te maken aan andere objecten. Daar acces-methodes voor gebruiken is enerzijds zinloos (ding verandert toch niet) en anderzijds niet altijd even duidelijk (uit een methode komt tenslotte niet per se 2x dezelfde waarde).

Verwijderd

kasper_vk schreef op woensdag 01 juni 2005 @ 15:29:
Op die manier heb je feitelijk nooit call-by-reference; er wordt altijd een waarde op de stack gezet, welke nooit meer gebruikt wordt nadat de methode gereturned is.
-zucht- is het nou zo moeilijk om te begrijpen?

By call-by-reference wordt er een referentie naar de variable aan de functie meegegeven. Je kunt dus de inhoud (in geval van value type) of hetgeen de variable heen wijst (in geval van pointer type) in de functie veranderen.

Dit kan in java nooit. Daarom is het geen call-by-reference. Lees de literatuur er maar op na. Dat jij het niet wilt geloven betekent nog niet dat het dus niet zo is.

Om in te gaan op je comment. De waarde die op de stack wordt gezet is in het geval van call-by-reference het adres van de variable die je mee geeft. Dit kan bijvoorbeeld een 32bit integer-like value zijn. Hoe deze waarde precies gerepresenteerd wordt is implementatie afhankelijk, maar hetgeen er op de stack staat is dus een adres van een variable zelf.

Om op je 2de comment in te gaan. In Java heb je dus inderdaad nooit call-by-reference. In andere talen wel. Bijvoorbeeld in C++.

C++:
1
2
3
4
5
6
7
8
9
10
11
void foo( Integer* &x ) {
    x = new Integer(5);
}

void bar() {

   Integer* y = new Integer(1);
   foo ( y );
   // Nu hebben we echte call-by-reference semantics.
   // y wijst nu naar het object dat in foo aangemaakt is.
}
Effectief heeft markvleth gewoon gelijk; wat er namelijk wordt doorgegeven bij een method-call met objecten als variabelen, zijn referenties naar objecten.
Effectief heeft markvleth zwaar ongelijk. Of iets een reference (pointer) -is-, staat los van de manier waarop je iets doorgeeft aan een functie.
Volgens jou redenering zou je dan ook call-by-integer hebben, en call-by-long, en call-by-WeetIkWatType, etc.

Daarnaast vond ik jouw reply behoorlijk respectloos overkomen, m.a.w. een duidelijke flame[/quote]

Het is dan ook erg vermoeiend dat mensen bijna 10 jaar na het uitkomen van Java nog denken dat het call-by-reference semantics heeft....

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Verwijderd schreef op woensdag 01 juni 2005 @ 15:45:
Het is dan ook erg vermoeiend dat mensen bijna 10 jaar na het uitkomen van Java nog denken dat het call-by-reference semantics heeft....
Vermoeiend of niet, je reageert je maar ergens anders af. Ondanks de knipoog was je post gewoon een ordinaire troll, en die kunnen we hier niet gebruiken.

En nu weer on-topic graag. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • JaWi
  • Registratie: Maart 2003
  • Laatst online: 14-01 21:58

JaWi

maak het maar stuk hoor...

Hmm, even voor de duidelijkheid:

In Java wordt er wel degelijk gebruik gemaakt van pass-by-reference! Als een object als parameter aan een functie wordt meegegeven, dan wordt er een kopie van de referentie gegeven (=pass-by-value). Je krijgt dus een kopie van de referentie naar het oorspronkelijke object...

Statistics are like bikinis. What they reveal is suggestive, but what they hide is vital.


Verwijderd

...

[ Voor 101% gewijzigd door Verwijderd op 01-06-2005 16:01 ]


Verwijderd

Verwijderd schreef op woensdag 01 juni 2005 @ 15:33:
Als Java geen pass by reference heeft, zou het toch resultaat 5 moeten zijn :?
Pass-by-reference houdt in dat je de variable kunt wijzigen. Als je een reference by-value doorgeeft kun je wel het geen de reference heenwijst veranderen. Dat staat los van de variable.

Vreemd dat mensen dit zo slecht begrijpen, maar goed, nog maar een voorbeeldje:

Laten we even uitgaan dat in een gegeven implementatie geheugenadressen door pure integers gerepresenteerd worden. Laten we het Integer object in het geheugen afkorten door de integer die erin staat. Stel nu:

Integer X = new Integer(5);

Er wordt een variable genaamd X aangemaakt. Deze variable zelf staat op geheugen locatie "100". De nieuwe integer op de heap staat op locatie "1000". Nu staat er dus op locatie 100 het getal 1000.

100: 1000
....
1000: 5

Vervolgens roepen we een een functie met call-by-value:

foo ( X)

Op de stack wordt nu een copy van X zelf gezet. Zoals we boven zagen is X zelf het getal 1000.

Op de stack komt dus te staan :

1000

Een lokale variable Y in de functie wijst intern naar deze 1000. Aangezien deze Y een pointer is, zal je via deze value 1000 naar geheugen locatie 1000 kunnen gaan om te zien dat er daar een 5 staat. Ook kun je op locatie 1000 gaan schrijven. Laten we daar bijvoorbeel een 3 van maken.

Je kunt via deze methode echter niet bij locatie 100 komen. Namelijk, je kent deze locatie helemaal niet. Maak je nu een nieuwe Integer met waarde 1 die toevallig op adres 2000 komt, dan zal het volgende in het geheugen staan:

100: 1000
....
1000: 3
2000: 1

Verlaat je nu de functie, dan zal X (op adres 100) in je vorige stackframe nog steeds naar 1000 wijzen. De INHOUD van 1000 is wel veranderd, maar niet de LOCATIE waar X heenwijst.


Nu doe we call-by-reference.

Op de stack wordt nu niet een copy van de inhoud van X gezet, maar het adres van X zelf. Op de stack komt dus te staan:

100

In de functie zelf wijst er nu een lokale variable naar deze 100. De compiler genereerd code die deze dereferenced zodat je op adres 1000 uitkomt. Omdat Y een pointer type is moet je deze dus nogmaals dereferences om op de inhoud van adres 1000 uit te komen -> de 5. Deze kun je weer gewoon herschrijven. Laten er weer een 3 neerzetten.

Doe je nu een toekenning aan de lokale variable Y, dan verander je iets op adres 100. Maak je bv een nieuwe Integer met waarde 1 aan op adres 2000, dan zal in 100 de value 2000 komen:

100: 2000
....
1000: 3
2000: 1

Als je nu de functie verlaat dan zal X in je vorige stackframe daarwerkelijk naar de nieuwe geheugen locatie 2000 wijzen. Dit staat, zoals je ziet dus los van het veranderen van de inhoud van locatie 1000.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Nog es dan:
Java heeft geen echte call by reference zoals uit o.a. C bekend is, maar iets dat er sterk op lijkt. Sun noemt het zelf ook expres geen call by reference.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

leeko, blaas niet zo hoog van de toren. Ik ben het met je eens, maar feit blijft dat het nogal open staat voor verschillende interpretaties. Want wát pass je daadwerkelijk, een variabele of een object? Zolang dat niet is gedefinieerd heeft de discussie geen zin. En die definitie is nogal subjectief, de een vind dat je een variabele meegeeft, de ander het daadwerkelijke object waar de variabele naar wijst. In het eerste geval kent java idd geen pass-by-reference, in het tweede geval is dat de enige mogelijkheid als je met objects aan de gang gaat.

Ook is een pass by reference nogal syntactische suiker; zoals al eerder correct opgemerkt: onderwater wordt gewoon een waarde aan de callee meegegeven, die waarde geeft aan waar een instance staat. De C++ compiler zorgt er bijvoorbeeld voor dat alle bewerkingen op de reference daadwerkelijk effect hebben op het object waarnaar gerefereerd wordt. De twee bla functies en de calls ernaartoe zullen exact hetzelfde zijn:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void bla (int & x)
{
    x = 3;
}

void bla (int * x)
{
    *x = 3;
}

int main()
{
    int x = 1;
    bla(x);
    bla(&x);
}


Je kunt zeggen, de ene passt by reference, de ander niet want &x is geen l-value. Maar de int die gepassed wordt, wordt daadwerkelijk wel by reference gepassed. Het is puur de compiler die er wat syntactische suiker omheen strooit, zodat custom operators e.d. ook wat makkelijker te implementeren zijn. Als de taal het zou toestaan om een reference te reassignen naar een ander adres, dan zou zo'n reassignment niet te zien zijn in de caller. Dus wat is het dan, pass by reference of by value? (Retorische vraag)

En laten we nu weer ontopic reageren: Waarom data hiding (of waarom juist niet?)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

offtopic:
[quote].oisyn schreef op woensdag 01 juni 2005 @ 16:34:
leeko, blaas niet zo hoog van de toren.
[/quote]
Nou, dan maar een excuses voor het "of je bent dom". Deze opmerking was echt als een grapje bedoeld hoor! Ondanks de smiley ziet toch niet iedereen de humor evan in geloof ik.
Ook is een pass by reference nogal syntactische suiker
In veel gevallen wel, zeker in talen waar je een "adress-of" operator hebt. Zo kun je in C/C++ het bijna equivalente stukje code schrijven, die wel call by value is:

C++:
1
2
3
4
5
6
7
8
9
10
11
void foo( Integer** x ) {
    *x = new Integer(5);    
}

void bar() {

   Integer* y = new Integer(1);
   foo ( &y );
  // We hebben call by value gebruikt, en toch hebben we het geen y heenwijst
  // kunnen veranderen. In sommige gevallen liggen de concepten dicht bij elkaar.
}


Het verschil is dat je met call-by-reference altijd 1 niveau dieper reverse-dereferenced dan het "ding" wat je doorgeeft. Biedt jouw taal je die mogelijkheid al expliciet (& operator in C/C++) dan is het syntactic sugar. Biedt jouw taal je die mogelijkheid niet, maar is call-by-reference wel een optie, dan is dat de enigste mogelijkheid die je hebt.

In Java heb je beide niet, dus moet je altijd voor dergelijke situaties de Integer X uit mijn voorbeeld in een andere object wrappen. In de praktijk zie je wel eens een Object[1] als "call-by-reference" wrapper.

[ Voor 3% gewijzigd door Verwijderd op 01-06-2005 16:55 ]


Verwijderd

JaWi schreef op woensdag 01 juni 2005 @ 15:50:
Hmm, even voor de duidelijkheid:

In Java wordt er wel degelijk gebruik gemaakt van pass-by-reference! Als een object als parameter aan een functie wordt meegegeven, dan wordt er een kopie van de referentie gegeven (=pass-by-value). Je krijgt dus een kopie van de referentie naar het oorspronkelijke object...
Kijk dit is gewoon de correcte uitleg, klaar (met uitzondering van primitieven uiteraard).


In jouw voorbeeld met integer x kan je inderdaad niet de reference zelf waarmee de functie wordt aangeroepen ergens anders naar toe laten wijzen, maar je kan wel het object manipuleren waar die reference naar toe wijst.

Klaar punt uit.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nou, dan maar een excuses voor het "of je bent dom". Deze opmerking was echt als een grapje bedoeld hoor! Ondanks de smiley ziet toch niet iedereen de humor evan in geloof ik.
In een verhitte discussie moet je deze "grapjes" gewoon niet maken, simpel.

Modbreak:En laten we nu weer ontopic reageren: Waarom data hiding (of waarom juist niet?)

[ Voor 63% gewijzigd door .oisyn op 01-06-2005 17:07 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
cbijlsma schreef op woensdag 01 juni 2005 @ 14:38:
Per saldo gebruik je data-hiding dus alleen niet als de waarde van de variabele niet meer gewijzigd wordt na het inladen van de klasse (dus final)? In de overige gevallen wil je dus controle hebben / heb je controle nodig en gebruik je methodes om de waarde van een variabele op te halen als ik het goed begrijp...
Ook met overerving heb je heel veel aan data-hiding, doordat je de manier waarop een waarde wordt gewijzigd (of de controle daarop) of de manier waarop de waarde bij opvragen wordt gerepresenteerd kunt aanpassen. De feitelijke interface naar het object blijft hetzelfde, maar de daadwerkelijke bewerking wordt anders.

Verwijderd

Modbreak:Zoals ik al zei...

[ Voor 103% gewijzigd door .oisyn op 01-06-2005 17:11 ]


Verwijderd

Wat betrefd het data-hiding verhaal. Als je met data-hiding alleen gettters/setters vs direct field access bedoeld dan heeft dit zover ik weet nooit een nadeel en alleen maar voordelen.

Bedoel je tevens ermee dat je class grotendeels een blackbox is, en (veel) interne private data heeft, dan is dit punt discutabel.

De originele OO filosofie gaat van het blackbox principe uit (data abstraction). Echter, de wat nieuwere IOC strategie (Inversion Of Controll), gaat er van uit dat het object al zijn data extern aangeleverd krijgt dmv setters. Via deze strategie kun je je objecten laten configureren door aparte controllers. Spring maakt hier bijvoorbeeld veel gebruik van. Ook zijn je objecten dmv deze strategie veel beter te unit testen.

Zoals gezegd staat dit wel gedeeltelijk haaks op het OO principe. In het extreme geval ben je weer terug bij de C ADT's waarbij elke functie van het type de state mee kreeg. (in C waren de functies van een type dan een verzameling 'losse' globale functies, en de state was een struct die je telkens mee gaf).

Verwijderd

Zoals eigenlijk al gezegd is realiseer je met data hiding een scheiding tussen implementatie en interface.

Als je bijv een data structuur zoals een Set (verzameling) hebt, wil je als gebruiker van die Set niks te maken hebben met hoe die set nou eigenlijk werkt. Dat is allemaal aan de implementatie. Als je data hiding hebt, dan kan die Set gemaakt zijn met een Array, een Hash tabel en noem maar op, zonder dat je er iets van merkt als gebruiker van die Set.

Nu kan je opzich zeggen wat maakt het uit of de interne variabelen van buitenaf te zien zijn, en dan heb je strict gezien wel gelijk dat dat niet uit maakt, alleen werkt het als een bescherming voor de programmeur. Je KAN gewoon niet rotzooien in de interne variabelen waarmee je de hele state van het object kan verknoeien. De implementatie gaat er namelijk van uit dat de enige toegang tot de interne variabelen via de public methodes gaat (uitzonderingen daargelaten in dezelfde package etc, maar dat is niet van belang). Hiermee kan de impelentatie er dus van uit gaan dat de state van de variabelen correct blijft, omdat de enige operaties er op die van zich zelf zijn.

Ga je eenmaal knoeien van buiten die implementatie in de interne variabelen, dan kan je de boel aardig verknoeien.

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 11:51

Robtimus

me Robtimus no like you

Verwijderd schreef op woensdag 01 juni 2005 @ 17:16:
Zoals eigenlijk al gezegd is realiseer je met data hiding een scheiding tussen implementatie en interface.
En constante (static final) variabelen horen ook tot de interface. Daarom zijn deze vrijwel altijd public, ook omdat ze niet te wijzigen zijn.

Een goed voorbeeld is Math.PI; dit is duidelijk te zien als de waarde van PI. Een getPI() zou, zoals al gezegd, doen denken dat pi elke keer weer berekend zou worden.
Daar is geen echte regel over, meer een conventie.

Constanten die de buitenwereld nodig kan / zal hebben: public static final.
Constanten die alleen in de class zelf nodig zijn: private/protected static final (al naar gelang je sub classes toegang wil geven). Eventueel kan het ook zonder modifier zodat ze package visibility hebben.
Niet-constanten: private/protected, eventueel zonder modifier, en de benodigde getters en setters de visibility geven die ze nodig hebben.

De vuistregel is ook: hou de visibility zo beperkt mogelijk, en sta alleen maar toe wat nodig is. Dus als het kan private, zonder modifier / protected alleen als je ze nodig hebt in de package / sub classes, en public als het echt niet anders kan. Geldt voor zowel fields als methods.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Gewoon je instinct volgen dus ;) Het begint me allemaal duidelijk te worden nu want ik twijfelde echt aan het nut van deze beide opties...

Kort samengevat kan je dus stellen wat IceManX zei:
IceManX schreef op woensdag 01 juni 2005 @ 20:56:
[...]
Constanten die de buitenwereld nodig kan / zal hebben: public static final.
Constanten die alleen in de class zelf nodig zijn: private/protected static final (al naar gelang je sub classes toegang wil geven). Eventueel kan het ook zonder modifier zodat ze package visibility hebben.
Niet-constanten: private/protected, eventueel zonder modifier, en de benodigde getters en setters de visibility geven die ze nodig hebben.

De vuistregel is ook: hou de visibility zo beperkt mogelijk, en sta alleen maar toe wat nodig is. Dus als het kan private, zonder modifier / protected alleen als je ze nodig hebt in de package / sub classes, en public als het echt niet anders kan. Geldt voor zowel fields als methods.
Bedankt allemaal! _/-\o_

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 16-10-2025
edit: Laat maar, offtopic, en jullie posten veel te snel :P

[ Voor 95% gewijzigd door D-Raven op 02-06-2005 18:20 ]


  • jAnO!
  • Registratie: Januari 2002
  • Laatst online: 01-05 18:22

jAnO!

lalalavanillevla

cbijlsma schreef op woensdag 01 juni 2005 @ 12:11:
Wat ik me dus afvraag is: wat voor voordelen heeft de data hiding nou boven het public declareren van de variabelen?

Misschien heeft iemand van jullie hier een heldere kijk op waarvoor alvast dank :)
Het duidelijkst vind ik altijd dit voorbeeld:

Stel je hebt een Klasse Kat met een int variabele gewicht. Als je gewicht public maakt kan iemand bijvoorbeeld het gewicht van de kat op -6 zetten... Ahhh andere code die bijv. dosis medicijn uitrekent klapt...

Door member variabelen private te maken (rule of thumb: dat doe je (bijna) altijd!)) kan je in de set methode (setter of constructor) validatie uitvoeren op de waarde.

When some people work at a place for ten years they get ten years of experience, other people work at a place for ten years and get one year of experience ten times.

Pagina: 1