1 van 1

constructors in java

Geplaatst: za 28 nov 2015, 23:55
door gogeta
Ik begrijp nog niet helemaal hoe een constructor werkt in java en daardoor de volgende vraag niet kan beantwoorden:
Gegeven zijn de class A en B:
 

Code: Selecteer alles

class A {
  char c;
  A () { // first Constructor
    c = 'A';
  }

  A (char c) { // second Constructor
    this.c = c;
  }

  void next () { // method
    if (c == 'Z') {
      c = 'A';
    } else {
      c = (char)(c+1);
    }
  }


class B {
  A a1; // declaration
  A a2;

  B (A a) { // construction
    a1 = a;
    a2 = new A(a.c);
  }

  void set (A a) { // method
    a1 = a2;
    a2 = a;
  }
}
 
en een stukje code van een programma:
 

Code: Selecteer alles

A a = new A();
B b = new B(a);
PrintStream out = new PrintStream(System.out);

void println (A x, B y) {
  out.printf("%c, %c, %c\n", x.c, y.a1.c, y.a2.c);
}


void doSomething () {
  println(a, b);
  a.next();
  println(a, b);
}
De bedoeling is dat ik dan moet geven wat de output moet zijn. Voor zover ik weet wordt een constructor eenmalig
gelezen door het programma en geeft deze een beginwaarde aan de variabelen die gedefinieerd zijn. Als ik de code stap voor stap volg dan zou de output van de eerste regel A, A, A moeten zijn.
Dat a.next()  c='A' in c='B' verandert is ook wel duidelijk, maar wat de output moet zijn is mij een raadsel.

Re: constructors in java

Geplaatst: zo 29 nov 2015, 00:55
door Xenion
Een constructor is een functie die wordt aangeroepen wanneer er een nieuw object wordt aangemaakt van een bepaalde klasse. Een klasse kan verschillende constructors hebben zodat het mogelijk is om nieuwe objecten aan te maken volgens verschillende input-argumenten.
 
Het is in deze oefening de bedoeling dat je analyseert waar er nieuwe objecten worden aangemaakt en waar er referenties naar al bestaande objecten worden gebruikt. Hoeveel verschillende objecten van klasse A en klasse B worden er in dit programma aangemaakt?

Re: constructors in java

Geplaatst: zo 29 nov 2015, 00:58
door gogeta
Xenion schreef: Een constructor is een functie die wordt aangeroepen wanneer er een nieuw object wordt aangemaakt van een bepaalde klasse. Een klasse kan verschillende constructors hebben zodat het mogelijk is om nieuwe objecten aan te maken volgens verschillende input-argumenten.
 
Het is in deze oefening de bedoeling dat je analyseert waar er nieuwe objecten worden aangemaakt en waar er referenties naar al bestaande objecten worden gebruikt. Hoeveel verschillende objecten van klasse A en klasse B worden er in dit programma aangemaakt?
Er worden 2 objecten aangemaakt. Eén van type A en een ander van type B.

Re: constructors in java

Geplaatst: zo 29 nov 2015, 10:49
door Xenion
Je kijkt niet ver genoeg. Wat gebeurt er wanneer je een object van class B aanmaakt?
PS: als je code tags gebruikt dan wordt code die je post leesbaarder. Ik heb het nu even zelf aangepast in jouw post.

Re: constructors in java

Geplaatst: zo 29 nov 2015, 11:55
door gogeta
Xenion schreef: Je kijkt niet ver genoeg. Wat gebeurt er wanneer je een object van class B aanmaakt?

PS: als je code tags gebruikt dan wordt code die je post leesbaarder. Ik heb het nu even zelf aangepast in jouw post.
 
Dat gebeurt hier (denk ik):                                         B b = new B(a);
Wat er hier gebeurt is dat je de constructor aanroept van class B. Je geeft 'm a mee als input. In class B zijn 2 variabelen gedefinieerd van type A.
a1 stel je dan gelijk aan a.
Voor a2 moet je nog een extra stap maken, omdat je weer een constructor van class A aanroept. In dit geval is het de tweede constructor. Die stelt c gelijk aan de c in(a.c) die je mee hebt gegeven.
 
Bedankt. Een stuk overzichtelijker op deze manier.

Re: constructors in java

Geplaatst: zo 29 nov 2015, 17:43
door Xenion
Ok, dus om het nog eens op een rijtje te zetten:
 
1) er wordt een nieuw object a van class A aangemaakt
2) er wordt een nieuw object b van class B aangemaakt
2a) in b wordt a1 gelijk gesteld aan a
2b) er wordt een nieuw object a2 gemaakt dat een kopie is van a
(In totaal zijn er dus 3 en niet 2 objecten.)
 
Nu wordt er op a de next() methode uitgevoerd. Wat is er nu allemaal gebeurd en wat zou dan de output van de call println(a,b) zijn?

Re: constructors in java

Geplaatst: zo 29 nov 2015, 20:25
door gogeta
Xenion schreef: Ok, dus om het nog eens op een rijtje te zetten:
 
1) er wordt een nieuw object a van class A aangemaakt
2) er wordt een nieuw object b van class B aangemaakt
2a) in b wordt a1 gelijk gesteld aan a
2b) er wordt een nieuw object a2 gemaakt dat een kopie is van a
(In totaal zijn er dus 3 en niet 2 objecten.)
 
Nu wordt er op a de next() methode uitgevoerd. Wat is er nu allemaal gebeurd en wat zou dan de output van de call println(a,b) zijn?
 
Hier kom ik dus niet uit.
 
a.next(); roept de methode next(); op in class A;
Aangezien c gelijk is aan 'A', verandert deze nu in c='B'. Hiermee is a.c dus verandert in 'B'.
a1 is gelijk aan a, dus is a1.c='B'.
 
Als ik voor a2 de constructor van B volg:
 
a2 = <b>new</b> A(a.c);
 
c is hierin B.
 
A (<b>char</b> c) { // second Constructor
<b>        this</b>.c = c;
}
 
c van class A wordt gelijkgesteld aan de c die je hebt meegegeven, dus 'B'. Hiermee zou a2 ook gelijk moeten zijn aan 'B'?

Re: constructors in java

Geplaatst: zo 29 nov 2015, 21:14
door Xenion
Nee dat klopt niet. Je denkt teveel in termen van 'klassen' ipv 'objecten'.
Het is belangrijk dat je weet hoeveel objecten er in je programma 'in leven' zijn en welke variabelen een referentie naar dat object bevatten.
 
a.next() wordt pas aangeroepen nadat je het object b hebt aangemaakt. Tijdens het aanroepen van de constructor A(char c) is a.c dus nog gewoon gelijk aan 'A'.
 
Heb je trouwens al eens geprobeerd om die code uit te voeren en te volgen via de debugger?

Re: constructors in java

Geplaatst: ma 30 nov 2015, 10:56
door gogeta
Xenion schreef: Nee dat klopt niet. Je denkt teveel in termen van 'klassen' ipv 'objecten'.
Het is belangrijk dat je weet hoeveel objecten er in je programma 'in leven' zijn en welke variabelen een referentie naar dat object bevatten.
 
a.next() wordt pas aangeroepen nadat je het object b hebt aangemaakt. Tijdens het aanroepen van de constructor A(char c) is a.c dus nog gewoon gelijk aan 'A'.
 
Heb je trouwens al eens geprobeerd om die code uit te voeren en te volgen via de debugger?
 
 
De debugger bevestigt dat a.next(); a2 niet verandert, maar waarom verandert a1 dan wel mee en a2 niet? Ze worden toch beide bepaald door c?

Re: constructors in java

Geplaatst: ma 30 nov 2015, 11:03
door Xenion
Dat is exact wat ik bedoelde met onderscheid zien tussen objecten en klassen :)
 
OK wat er gebeurt:

Code: Selecteer alles

A a = new A() // dit maakt een nieuw object aan van klasse A
B b = new B(a) // dit maakt een nieuw object aan van klasse B
Bij het aanmaken van een nieuw B object moeten we in de constructor gaan kijken:

Code: Selecteer alles

B (A a) {
  a1 = a; // a1 wordt gelijk gesteld aan a (b.a1 en a zijn dus hetzelfde object)
  a2 = new A(a.c); // voor a2 wordt er een nieuw A-object aangemaakt met dezelfde c-waarde als a
}
Nu gaan we a.next() aanroepen. Dit zorgt ervoor dat a.c nu gelijk wordt aan 'B' ipv 'A'.
Omdat b.a1 een referentie is naar hetzelfde object als a, zal b.a1.c nu ook gelijk zijn aan 'B'.
b.a2 is echter een ander object en op dit object werd niet de next() methode uitgevoerd dus, b.a2.c blijft gewoon gelijk aan 'A'.
 
Een klasse kan je zien als een bouwplan voor een huis. Vanuit een bouwplan kan je verschillende huizen (objecten) bouwen, maar het is niet omdat je in 1 huis een raam open zet dat dit raam in de andere huizen ook open zal staan.
Het verschil tussen een object en een klasse is trouwens een vraag die al eens gesteld wordt bij sollicitatiegesprekken voor IT functies ;)

Re: constructors in java

Geplaatst: di 01 dec 2015, 15:48
door gogeta
Xenion schreef: Dat is exact wat ik bedoelde met onderscheid zien tussen objecten en klassen :)
 
OK wat er gebeurt:

Code: Selecteer alles

A a = new A() // dit maakt een nieuw object aan van klasse A
B b = new B(a) // dit maakt een nieuw object aan van klasse B
Bij het aanmaken van een nieuw B object moeten we in de constructor gaan kijken:

Code: Selecteer alles

B (A a) {
  a1 = a; // a1 wordt gelijk gesteld aan a (b.a1 en a zijn dus hetzelfde object)
  a2 = new A(a.c); // voor a2 wordt er een nieuw A-object aangemaakt met dezelfde c-waarde als a
}
Nu gaan we a.next() aanroepen. Dit zorgt ervoor dat a.c nu gelijk wordt aan 'B' ipv 'A'.
Omdat b.a1 een referentie is naar hetzelfde object als a, zal b.a1.c nu ook gelijk zijn aan 'B'.
b.a2 is echter een ander object en op dit object werd niet de next() methode uitgevoerd dus, b.a2.c blijft gewoon gelijk aan 'A'.
 
Een klasse kan je zien als een bouwplan voor een huis. Vanuit een bouwplan kan je verschillende huizen (objecten) bouwen, maar het is niet omdat je in 1 huis een raam open zet dat dit raam in de andere huizen ook open zal staan.
Het verschil tussen een object en een klasse is trouwens een vraag die al eens gesteld wordt bij sollicitatiegesprekken voor IT functies ;)
 
 
Beste Xenion,
 
bedankt voor de moeite en de tijd die je ervoor hebt genomen. Het is nu een stuk duidelijker.

Re: constructors in java

Geplaatst: di 08 dec 2015, 20:59
door gogeta
 

Code: Selecteer alles

class M {
	String s;
	M () {
		s = "k";
	}

	M (String s) {
		this.s = s;
	}

}
 

Code: Selecteer alles

class Problem{
	static final int MAX_LENGTH_RIJ = 4;
	PrintStream out;
	M m;
	M[] rij;
	String s;

	Problem(){
		out = new 
		PrintStream(System.out);
		rij = new 
		M[MAX_LENGTH_RIJ];
		m=new M();
		s="p";
		for (int i = 0; i < rij.length; i++) {
			rij[i] = new M(s);
		}
	}


	void m1 (M m) {
		m = new M("12");
	}

	void m2 (M[] r, int i) {
		r[i] = new M("34");
	}



	void println (M m){
		out.printf("%s\n", m.s);
	}

	void doeIets () {

Code: Selecteer alles

		m1(m);
		m2(rij, 2);
		println(m);
		println(rij[2]);
	}
}


 
Ik loop weer tegen een probleem aan. Bij m1(m) wordt m niet vervangen door het nieuwe object dat wordt aangemaakt in de methode, terwijl dit bij m2 wel het geval is. Waarom?





 





Re: constructors in java

Geplaatst: wo 09 dec 2015, 02:13
door Xenion
Nee dat is inderdaad iets tricky. Heb je nergens een hoofdstuk of paragraaf in je handboek die uitlegt dat Java functieargumenten doorgeeft "by value" (pass by value)?
 
In m1 krijg je een kopie van een referentie naar een object mee. In de functie zelf zeg je dan "**** it". Waar die referentie nu naar wijst kan met niet schelen. Ik maak een nieuw object en laat het daarnaar wijzen. Maar omdat het om een kopie van 'm' gaat, zal 'm' zelf niet veranderen en gewoon 'null' blijven.
 
In m2 is het anders. Daar krijg je een kopie van een referentie naar een array object. In dat array object zitten weer referenties en daar ga je er eentje van aanpassen. Daardoor heb je effectief het element op index 2 in 'rij' veranderd.

Re: constructors in java

Geplaatst: wo 09 dec 2015, 08:42
door gogeta
Xenion schreef: Nee dat is inderdaad iets tricky. Heb je nergens een hoofdstuk of paragraaf in je handboek die uitlegt dat Java functieargumenten doorgeeft "by value" (pass by value)?
 
In m1 krijg je een kopie van een referentie naar een object mee. In de functie zelf zeg je dan "**** it". Waar die referentie nu naar wijst kan met niet schelen. Ik maak een nieuw object en laat het daarnaar wijzen. Maar omdat het om een kopie van 'm' gaat, zal 'm' zelf niet veranderen en gewoon 'null' blijven.
 
In m2 is het anders. Daar krijg je een kopie van een referentie naar een array object. In dat array object zitten weer referenties en daar ga je er eentje van aanpassen. Daardoor heb je effectief het element op index 2 in 'rij' veranderd.
 
Ok. Nog een keer op een rijtje.
 
In methodes wordt een kopie gemaakt van de referentie en niet van de objecten zelf.
 
In m2 wordt een kopie gemaakt van de eerste referentie naar een array-object.
Het array-object is hetzelfde object als die je in class hebt gedefinieerd.
Dat geldt ook voor alle referenties naar andere objecten in het array-object.
Daarom is elke verandering in dat object "effectief".
 
 
In m1  wordt een kopie gemaakt van een referentie naar een M-object.
In m1 verander je die referentie (dus het kopie), waardoor er daarbuiten geen effectieve verandering plaatsvindt.
Het object zelf is verder onveranderd gebleven.

Re: constructors in java

Geplaatst: wo 09 dec 2015, 09:49
door Xenion
Ik denk dat je het begrijpt. Hieronder nog eens hetzelfde maar dan lichtjes anders verwoord.
Uit nieuwsgierigheid: waar kom je dit soort problemen tegen? Welke unief, jaar en studierichting?
 
Bekijk volgend eenvoudiger voorbeeld eens.

Code: Selecteer alles

void f(int a){
    a = 5;
}

void main(){
    int myInteger = 7;
    f(myInteger);
    print(myInteger);
}
Bij het aanroepen van de functie f wordt er een nieuwe integer a aangemaakt met dezelfde waarde als myInteger. Het veranderen van a zal dus myInteger niet beïnvloeden. Die blijft gewoon gelijk aan 7.
 
Stel nu dat je het met jouw 'M' klasse zou doen:

Code: Selecteer alles

void f(M a){
    a = new M("M vanuit de functie");
}

void main(){
    M myM = new M("test");
    f(myM);
    print(myM);
}
Wanneer je nu f aanroept zal er een nieuwe referentie 'a' naar een M object worden aangemaakt. Deze zal initieel wijzen naar hetzelfde object als waar 'myM' naar wijst. In de functie zeg je echter dat je 'a' naar een nieuw M object wil laten wijzen. Dit beïnvloedt 'myM' dus niet.
 
Met een array van M's is het hetzelfde. Jouw functie void m2(M[] r, int i) krijgt een kopie van een referentie naar een array mee. Je gaat hier echter niet zeggen dat je 'r' naar een nieuwe array wil laten wijzen. In de array waar r naar wijst wil ik op index 2 een new M("34") zetten en aangezien je aan de referentie 'r' zelf niks verandert hebt wijst die nog gewoon naar de 'rij' array.
 
Hopelijk is het hiermee een beetje duidelijker.