Parent variabele in child class
Ik wil in mijn child class de waarde welke in de parent staat opvragen.
Als ik onderstaande doe dan krijg ik na $b->getVal() als waarde a terug. Hier verwachtte ik c.
Ik begin me nu te te verdiepen in OOP en ben wat dingen aan het uitproberen. Al doende leert men.
Ik weet dat dit waarschijnlijk basis materiaal is maar hier loop ik tegenaan.
Wat moet ik doen om na $b->getVal() als resultaat c te krijgen?
Code (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
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
class A {
protected $_value;
private function __construct() {
$this->_value = 'a';
}
public function setValue($val) {
$this->_value = $val;
}
protected function getValue($val) {
return $this->_value;
}
}
class B extends A {
private function __contruct() {
parent::__construct();
}
public function getVal() {
return parent::getValue();
}
}
$a = new A;
$b = new B;
$a->setValue('c');
echo $b->getVal();
protected $_value;
private function __construct() {
$this->_value = 'a';
}
public function setValue($val) {
$this->_value = $val;
}
protected function getValue($val) {
return $this->_value;
}
}
class B extends A {
private function __contruct() {
parent::__construct();
}
public function getVal() {
return parent::getValue();
}
}
$a = new A;
$b = new B;
$a->setValue('c');
echo $b->getVal();
Gewijzigd op 02/12/2015 15:23:07 door Sander Z
Edit. Verder moet een constructor van een klasse overigens public zijn, anders kan er geen object worden geconstrueerd.
Gewijzigd op 02/12/2015 15:32:36 door Ward van der Put
Ik zit nu in de auto en zat het nog te overdenken. Ik kwam al tot dezelfde conclusie. Ik denk ondertussen ook te weten hoe het wel te bereiken wat ik wil. Ik ga straks thuis weer even experimenteren.
Bedankt in ieder geval.
Nergens komt daarin object $a voor.
>> Ik denk ondertussen ook te weten hoe het wel te bereiken wat ik wil.
Misschien kun je dat straks nog even posten? Er zijn namelijk voor de meeste OOP-dingen design patterns bedacht en waarschijnlijk zijn er wel een of twee te noemen waarmee je dat doel kunt bereiken.
Toevoeging op 02/12/2015 17:33:41:
Dit is hoe ik uiteindelijk bereikte wat ik wilde:
Code (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
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
class A {
protected $_value;
public function __construct() {
$this->_value = 'a';
}
public function setValue($val) {
$this->_value = $val;
}
}
class B extends A {
public function __contruct() {
parent::__construct();
}
public function getVal() {
return $this->_value;
}
}
$b = new B;
$b->setValue('c');
echo $b->getVal(); // c
protected $_value;
public function __construct() {
$this->_value = 'a';
}
public function setValue($val) {
$this->_value = $val;
}
}
class B extends A {
public function __contruct() {
parent::__construct();
}
public function getVal() {
return $this->_value;
}
}
$b = new B;
$b->setValue('c');
echo $b->getVal(); // c
Gewijzigd op 02/12/2015 17:34:22 door Sander Z
Code (php)
Twee verschillen:
• Als je de constructor van class B weglaat, wordt automatisch de constructor van class A gebruikt.
• Aangezien je in de constructor van class A alleen een eigenschap instelt, kun je die eigenschap ook rechtstreeks definiëren en de constructor van class A weglaten.
Ward van der Put op 02/12/2015 15:30:11:
Edit. Verder moet een constructor van een klasse overigens public zijn, anders kan er geen object worden geconstrueerd.
Wordt hier niet juist gebruik van gemaakt (een niet-publieke __construct methode) bij de implementatie van bepaalde design patterns om af te dwingen dat er geen objecten geïnstantieerd kunnen worden (althans niet via de standaard weg)? Zoals een Factory?
Ik kan mij vergissen, design patterns zijn niet mijn sterkste punt maar ik heb weleens implementaties van *iets* gezien waarbij bewust geen publiek toegankelijke constructor werd gebruikt.
/offtopic
Thomas van den Heuvel op 02/12/2015 19:42:35:
Ik kan mij vergissen, design patterns zijn niet mijn sterkste punt maar ik heb weleens implementaties van *iets* gezien waarbij bewust geen publiek toegankelijke constructor werd gebruikt.
Klopt, dan heb je het bijvoorbeeld over het service Locator pattern aka registry pattern, dat bij PHP vaak een singleton pattern interface implementeert:
Net zoals bij de centrale registry van een besturingssysteem is er maar één service locator c.q. registry, zodat services kunnen worden gedeeld door klassen, subsystemen, applicaties, enzovoort. Daarom wordt het gebruik van de constructor en de magische methode __clone() verboden:
Code (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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php
class Registry implements SingletonInterface
{
/**
* @var array $Data
* @var object|null $Instance
*/
private $Data = array();
private static $Instance = null;
// Disable object instantiation and cloning
private function __construct() {}
private function __clone() {}
/**
* Get the single instance of the registry.
*
* @param void
* @return self
*/
public static function getInstance()
{
if (self::$Instance === null) {
self::$Instance = new Registry();
}
return self::$Instance;
}
/**
* Set a shared value in the global registry.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function set($key, $value)
{
$this->Data[$key] = $value;
}
/**
* Get a value from the registry.
*
* @param string $key
* @return mixed|null
*/
public function get($key)
{
return (isset($this->Data[$key]) ? $this->Data[$key] : null);
}
}
?>
class Registry implements SingletonInterface
{
/**
* @var array $Data
* @var object|null $Instance
*/
private $Data = array();
private static $Instance = null;
// Disable object instantiation and cloning
private function __construct() {}
private function __clone() {}
/**
* Get the single instance of the registry.
*
* @param void
* @return self
*/
public static function getInstance()
{
if (self::$Instance === null) {
self::$Instance = new Registry();
}
return self::$Instance;
}
/**
* Set a shared value in the global registry.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function set($key, $value)
{
$this->Data[$key] = $value;
}
/**
* Get a value from the registry.
*
* @param string $key
* @return mixed|null
*/
public function get($key)
{
return (isset($this->Data[$key]) ? $this->Data[$key] : null);
}
}
?>
Dit design pattern garandeert dat er maar één instantie van de registry in omloop is:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
// Fatal error: Call to private Registry::__construct()
$registry = new Registry();
// Het moet zo:
$registry = Registry::getInstance();
?>
// Fatal error: Call to private Registry::__construct()
$registry = new Registry();
// Het moet zo:
$registry = Registry::getInstance();
?>
Volgens sommigen zijn dit anti-patterns, onder andere omdat je een tightly-coupled systeem krijgt waarin (te) veel afhankelijk is gemaakt van één God particle. Praktisch bezwaar is daarnaast dat je unit tests niet zuiver kunt houden.
Bedankt voor de moeite om me nog wat extra's mee te geven!
Wordt gewaardeerd!
Ward van der Put op 02/12/2015 18:01:19:
• Als je de constructor van class B weglaat, wordt automatisch de constructor van class A gebruikt.
Ok duidelijk. Maar als ik in class B toch wel iets via zijn constructor zou willen doen dan is dit wel nodig?:
Of is dat sowieso niet nodig?
Gewijzigd op 03/12/2015 15:10:57 door Sander Z
Er zijn namelijk ook situaties denkbaar waar de constructor geheel iets anders doet, dus de constructor van class B die van class A geheel vervangt of "overschrijft". Dat geldt ook voor andere methoden die een child class erft van de parent.
Verder biedt het je dan de mogelijkheid om de volgorde van de operaties zelf te bepalen: direct de constructor van A aanroepen en dan die van B iets extra's laten doen of omgekeerd juist eerst in de constructor van B iets extra's doen en daarna pas de constructor van de parent aanroepen.
Wederom thanks!