[PHP] Class-instance gebruiken in andere class

Pagina: 1
Acties:

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 12-02 15:52
Tja, hoe stel je deze vraag..

index.php:
PHP:
1
2
3
4
5
6
7
require_once("TCart.php");
require_once("TMessage.php");

$cart = new TCart();
$mesg = new TMessage();

$cart->call_error();

TCart.php
PHP:
1
2
3
4
5
6
7
class TCart() {

  function call_error() {
    // call to function "DoSomething" in class TMessage ($mesg)
  } // function

} // class

TMessage.php
PHP:
1
2
3
4
5
6
7
8
class TMessage() {

  function DoSomething() {
    print "Done something!";
    exit();
  } // function

} // class


In de index.php maak ik twee instanties van classen, TCart & TMessage. Normaliter roep ik de functies van de twee verschillende instanties aan vanuit de index.php, zodat ik de DoSomething() functie van de TMessage-class vanuit de index.php. Dat werkt logischerwijs.

Het probleem: Ik wil de DoSomething() functie van de TMessage-instantie vanuit de TCart-instantie aanroepen. Hoe doe je zoiets "netjes"? global $mesg; in de TCart zetten lijkt mij niet bepaald netjes... Maar hoe dan?

Verwijderd

PHP:
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
class TCart {
  var $mesg;

  function TCart(&$mesg)
  {
     $this->mesg = $mesg;
  }

  function call_error() {
     $this->mesg->DoSomething();    
  } // function

} 

Class TMessage {

  function DoSomething() {
    print "Done something!";
    exit();
  } 
} 

$mesg = new TMessage();
$cart = new TCart(&$mesg);

$cart->call_error();


ongeveer zo, ik weenie zeker of ik genoeg &&& heb en of ze precies goed staan..

als je die mesg perse NIET in de constructor van TCart wilt hebben kun je nog een function setMessage(&$mesg) maken in klasse TCart waar je $this->mesg dus set. Je moet dan wel ff in call_error() even checken of $this->mesg niet null is of wel een object is of isset() is of welke manier dan ook om te controleren of er al een setMessage geweest is...

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 12-02 15:52
Hmm tjsa.. Goh.. Hmm... dus... want.. Waarom ben ik nog niet wakker? ;) Redelijk sim-pel inderdaad. Gewoon de instantie aan de class meegeven :) Whooooot t00t h0nk (à la Baz_) :+

Goh, thanx.. Ik ga koffie zetten :)

Verwijderd

en denk er ff aan (na je koffie) dat een klasse geen haken (()) hoeft maar alleen accolades..

class Blaat {
}

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 12-02 15:52
Goh hé ja, ook dat nog :) Dat hoeft alleen in de constuc.TAR :)
edit:
Hee maar dat had ik ook al.. Waarom doe ik het in dit voorbeeldje dan fout? |:(

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op 30 augustus 2002 @ 14:16:

ongeveer zo, ik weenie zeker of ik genoeg &&& heb en of ze precies goed staan..
Nope. Niet genoeg, en ze staan fout ;)

Dit mag niet (meer) $a = new Something(&$b); Je moet dan de ctor van Something zo maken: function Something(&$b); en dan die ampersand bij de new call weglaten.

Overigens heb ik net een stuk gepost over een soort gelijk probleem, misschien dat je daar meteen op kan letten :)

[rml][ PHP] Reference probleem(pje)[/rml]

edit:
Wordt dan zoiets:

PHP:
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
32
<?
class TCart { 
  var $mesg; 

  function TCart(&$mesg) 
  { 

     $this->mesg =& $mesg; // !!! hier OOK een & anders nog steeds copy
  } 

  function call_error() { 
     $this->mesg->DoSomething();     
  } // function 

}  

Class TMessage { 

  function DoSomething() { 
    print "Done something!"; 
    exit(); 
  }  
}  

$mesg = new TMessage(); 

// hier OOk =&, anders copy na new en automatisch copy van TMessage
// en geen & voor $mesg
$cart =& new TCart($mesg); 

$cart->call_error();
?> 

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 12-02 15:52
Oe ja.. Laat ik dat dan ook maar eens uit gaan zoeken... Het geheugengebruik bij kopieën van classes... Nou is TMessage niet zo'n hele grote, maar toch.. &-netjes.. Draadje lezen..

In de contruc.TAR moet er dus een & voor het argument om er géén kopie van te maken? Dan wordt dus echt de instantie van TMessage gebruikt in plaats van een kopie te maken van de al bestaande instantie? Kee dan.. En bij $this->mesg = &$mesg; lijkt me dan ook logisch..

Maar wat bedoel je met regel 27/28 (de uitleg op regel 29)? Wat gebeurt er anders? Dat volg ik niet helemaal..

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Misschien is het handig om dit eens door te lezen....

[rml][ Design Pattern] Elke class beschikbaar maken[/rml]

Programmer - an organism that turns coffee into software.


  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 12-02 15:52
Ik heb het net doorgelezen.. Wat ik er uit begrijp: PHP is lek :/ Instanties van classes gebruiken (in mijn geval de instantie van TMessage) in andere instanties (hier dus een instantie van TCart) dmv een reference naar de instantie van TMessage door te geven is geen goed idee. Toch? Dat is alles wat ik wil namelijk.. Meer hoeft het niet te kunnen: het project is bijna klaar, in het volgende project ga ik er écht goed naar kijken.

Ik wil dus nu simpelweg $M (instantie van TMessage) gebruiken in andere klasses. Is het een idee om de manier die fladder aangaf te gebruiken, met toevoeging van een paar &-etjes?

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class TMessage {
 function DoSomething() {
  print "Done something";
  exit();
 } // function
} // class

class TCart {
 var $M;
 function TCart(&$M) {
  $this->M = &$M;
 } // function
 function CallInTMessage() {
  $this->M->DoSomething();
 } // function
} // class

$M = new TMessage();
$cart = new TCart($M);

$cart->CallInTMessage();


Is dit etisch verantwoord?

[ Voor 0% gewijzigd door DRvDijk op 30-08-2002 16:34 . Reden: Variabele hernoemd ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Het kan wel, maar het doet niet wat je denkt. Je werkt namelijk niet op de globale $M nu. Als TMessage dus state bijhoud, bv een errorcode oid, dan kan je die in TCart wel zetten, maar in $M zal die niet gezet zijn.

Dus wordt het $cart =& new TCart($M). Dat is ook wat ik zei bij regels 27/28.

Normaal gesproken maakt PHP na "new" een kopie. Elke "operator =" maakt een kopie. Dus wat er bij "new" gebeurt is dat er een temporary TCart wordt aangemaakt, en die wordt dan gekopieerd naar $cart.

Je moet goed bedenken dat references in PHP geen pointers zijn (ook geen C++ references), maar "aliases". Het is alleen een andere naam voor hetzelfde object. Als je dus een kopie maakt van een reference, dan kopieer je niet de reference (want die bestaat niet als entiteit) maar het echte object zelf.

Nu maakt dat iha niet zo heel veel uit, want PHP maakt pas een echt kopie als je de state van een object wijzigd. In jouw voorbeeld maakt het dus alleen uit als TMessage state heeft, en die gewijzigd wordt door doSomething(); en je dan later die state wilt opvragen op $M.

Ik hoop dat het een beetje duidelijk is. Lastig uit leggen. Het sleutel begrip is "alias". Er bestaat geen reference als entiteit, je kan een reference niet kopieren. Een reference IS het object zelf. (dit komt weer aardig overeen met C++, alleen kan je in C++ WEL references kopieren)

Overigens zou dit probleem worden opgelost door copy-constructors zoals in de nieuwe PHP versie. Je kan dan een shallow copy maken, nu zijn alle kopieen "Deep".

edit:

Nog een keer duidelijker, in jouw code wordt er op regel 19 door de "=" een deep-copy gemaakt van TCart, en werk je dus op een andere instantie van TMessage (niet $M)

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 12-02 15:52
Ik wil toch wél een kopie van TCart, maar niet van $M (instantie TMessage)?

Ik snap niet dat als je $cart = new TCart(&$M); doet, er een kopie van $M gemaakt wordt. Da's niet echt logisch.. Ik gelóóf wel dat het gebeurt, daar niet van..

Als ik $cart =& new TCart($M); doe, dan wordt er geen kopie van TCart gemaakt? Hoe kan dat dan? Er moet toch een instantie van TCart gemaakt worden? Of gebeurt dat ook?

Ik ga even spelen doen..
$cart =& new TCart($M);
Dat zegt dus: $cart is TCart, en geef daar de instantie $M (van TMessage) aan mee. Daarmee maak je dus géén kopie, én niet van TCart, én niet van de TMessage-instantie, $M.

Hmm, waarom dan niet iets als: $cart =& new TCart(&$M); ?

offtopic:
Ik heb je aan m'n ICQ-lijst toegevoegd.. #4405650

[ Voor 0% gewijzigd door DRvDijk op 30-08-2002 17:50 . Reden: OT-tje ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Het gaat erom dat als je TCart kopieert, dat zijn member vars ook gekopieerd worden. En die member vars zijn hier 1 reference naar TMessage. PHP zal dus die member var kopieren, wat een reference is, en aangezien een ref het object IS (slechts een andere naam) wordt het echte object gekopieerd.

In deze situatie:

$m = new TMessage();
$cart = new TCart($m);

Bestaan er 3 geinstantieerde TMessage objecten, en 2 TCart objecten. Resp.: (new TMessage), ($m), ($cart->mesg) en (new TCart($m)), ($cart)

In de volgende situatie van beide slechts 1:
$m =& new TMessage();
$cart =& new TCart($m);

Nu geldt: $cart->mesg = $m = new TMessage();
en: $cart = new TCart()
Waarbij de '=' staat voor 'is andere naam voor'

De benaming "references" is erg fout vind ik persoonlijk. Ze hadden het "aliases" moeten noemen.

edit:

Dit alles onder de aanname van de volgende constructor voor TCart:
function TCart(&$mesg) {
$this->mesg =& $mesg;
}

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 12-02 15:52
Hmm dus als ik wél een kopie wil hebben van TCart, maar géén van TMessage, dan moet ik in de TCart-class een of andere functie maken die, nadat er een kopie van TCart gemaakt is ($cart = new TCart;) de alias accepteert..
function GetMessageInstance(&$M) { $this->M =& $M; }

en dan moet er dus eerst een TCart gekopiëerd worden, en daarna nog es die GetMessageInstance-functie aangeroepen..

$M = new TMessage;
$cart = new TCart;
$cart->GetMessageInstance($M);

right?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Hehehe :)

Of dus gewoon die "$cart =& new TCart($m)" gebruiken ;) De code die ik gaf werkt wel goed. Er is dus een verschil tussen "= new" en "=& new" :-)

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 12-02 15:52
Zoijar schreef op 30 augustus 2002 @ 15:22:
[...]
PHP:
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
32
<?
class TCart { 
  var $mesg; 

  function TCart(&$mesg) 
  { 

     $this->mesg =& $mesg; // !!! hier OOK een & anders nog steeds copy
  } 

  function call_error() { 
     $this->mesg->DoSomething();     
  } // function 

}  

Class TMessage { 

  function DoSomething() { 
    print "Done something!"; 
    exit(); 
  }  
}  

$mesg = new TMessage(); 

// hier OOk =&, anders copy na new en automatisch copy van TMessage
// en geen & voor $mesg
$cart =& new TCart($mesg); 

$cart->call_error();
?> 
Die code? Daar wordt dus geen kopie van TCart gemaakt als ik het goed zie toch?
Pagina: 1