[oop] property afdwingen?
Is er een manier om een class property af te dwingen?
Stel we hebben een abstracte class Bar. Hierin zou ik graag een abstracte class property in willen opnemen die door de child classes moet worden ingevuld. Dit lijkt echter niet te kunnen:
Zijn er andere mogelijkheden?
Nee, dat kan niet. Gebruik ipv een getter om af te dwingen. Zie hier weer zo'n zelfde geval als in het interface topic: je moet een gedrag afdwingen (method), niet in implementatie (property).
Probeer eens uit te leggen waarom je dit nu eigenlijk wilt? En begrijp dan dat het eigenlijk gewoon een beetje kolder is....
@Erwin: het zou fijn zijn als wanneer iemand een vraag stelt je daar niet meteen een waarde-oordeel aan hecht. Niet iedereen heeft dezelfde kennis als jij. Ik stel een serieuze vraag en vind het niet echt prettig als jij dat dan afdoet als "een beetje kolder". De ene mens weet veel van onderwerp A en de andere mens weet veel van onderwerp B. Zo gaat het nu eenmaal in het leven. Probeer dat feit aub te respecteren.
Ik heb een abstracte class. Ik wil aan de child classes een makkelijk leesbare naam geven. In de abstract class wil ik dan een getName method maken die de class property $name returnt. Maar dan moet dus wel iedere child class de property $name hebben. Vandaar dat ik me afvraag hoe je dat het beste kunt afdwingen.
Gewijzigd op 08/12/2013 23:31:38 door Ozzie PHP
Ozzie, ik zal me verder onthouden van antwoorden op je topics, dat is misschien beter.
Dat hoeft niet hoor Erwin. Je bijdrages zijn altijd ZEER nuttig en ik leer daar ook van. Alleen de sarcastische ondertoon mag soms een beetje minder ;) Sommige dingen zijn voor jou vanzelfsprekend en voor mij (nog) niet. Een forum is een ideaal medium om zelf dingen te leren en om dingen aan iemand anders te leren. Je moet er altijd vanuit gaan dat mensen met een reden een bepaalde vraag stellen... ook al kan dat in jouw ogen nog zo dom zijn. Blijkbaar weet iemand iets niet en dan is het toch alleen maar leuk als je iemand kunt helpen? Zo kijk ik er in ieder geval tegenaan. En ja, jij bent een stuk vergevorderder in deze materie dan ik, en juist daarom is het fijn als je mij helpt... maar dan graag zonder te zeggen dat ik dom of idioot ben :D
Ozzie PHP op 08/12/2013 23:31:06:
Ik heb een abstracte class.
OK:
Ozzie PHP op 08/12/2013 23:31:06:
In de abstract class wil ik dan een getName method maken.
Ozzie PHP op 08/12/2013 23:31:06:
Die getName() method returnt de class property $name. Maar dan moet dus wel iedere child class de property $name hebben.
Code (php)
Edit:
Ik had het gelukkig fout wat underscores en PSR standaarden betreft.
Quote:
Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.
Gewijzigd op 09/12/2013 10:53:14 door Dos Moonen
Ik hoop het niet... ;-)
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
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
<?php
abstract class Foo
{
private $Name;
/**
* @api
*
* @access final public zodat altijd deze constructor wordt gebruikt en
* alle childs daarmee de vereiste parameter $name implementeren.
*/
final public function __construct($name)
{
$this->setName($name);
}
final public function getName()
{
return $this->Name;
}
/**
* @internal
*
* @access final private zodat deze methode alleen intern kan worden gebruikt
* en daarmee de constructor de enige ingang wordt.
*/
final private function setName($name)
{
if (!is_string($name)) {
throw new \InvalidArgumentException('Name is not a string.');
} else {
$this->Name = $name;
}
}
}
?>
abstract class Foo
{
private $Name;
/**
* @api
*
* @access final public zodat altijd deze constructor wordt gebruikt en
* alle childs daarmee de vereiste parameter $name implementeren.
*/
final public function __construct($name)
{
$this->setName($name);
}
final public function getName()
{
return $this->Name;
}
/**
* @internal
*
* @access final private zodat deze methode alleen intern kan worden gebruikt
* en daarmee de constructor de enige ingang wordt.
*/
final private function setName($name)
{
if (!is_string($name)) {
throw new \InvalidArgumentException('Name is not a string.');
} else {
$this->Name = $name;
}
}
}
?>
Code (php)
De abstract parent class gebruikt dus een property $consumer_name uit de child classes en nu wil ik dus dat iedere child class zo'n property heeft. Dit wil ik op de een of andere manier kunnen afdwingen. Het mag ook een constante zijn, maar het gaat er dus om dat de abstract class gebruik kan maken van een waarde die in iedere child class aanwezig is.
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
<?php
abstract class Car
{
protected $consumer_name;
final public function __construct()
{
if (empty($this->consumer_name)) {
throw new \Exception('Consumer name not set.');
}
}
public function getConsumerName()
{
return $this->consumer_name;
}
}
class NoNameCar extends Car
{
// Oeps, property vergeten in te stellen
//protected $consumer_name = 'Hier had de naam gemoeten gemoeten';
}
// Gooit een exception
$car = new NoNameCar();
?>
abstract class Car
{
protected $consumer_name;
final public function __construct()
{
if (empty($this->consumer_name)) {
throw new \Exception('Consumer name not set.');
}
}
public function getConsumerName()
{
return $this->consumer_name;
}
}
class NoNameCar extends Car
{
// Oeps, property vergeten in te stellen
//protected $consumer_name = 'Hier had de naam gemoeten gemoeten';
}
// Gooit een exception
$car = new NoNameCar();
?>
Een alternatief is de exception uitstellen door deze te verplaatsen naar getConsumerName() omdat je daar de naam pas gebruikt.
Oké, dan zou het inderdaad zoiets moeten worden. Ik had het handiger gevonden als je gewoon een property kon afdwingen, maar dan moet ik het inderdaad in zo'n soort oplossing gaan zoeken. Thanks!
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
54
55
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
54
55
<?php
abstract class Miauw
{
protected $name;
final public function getName() // Final!
{
if ( ! is_string($this->name))
{
throw new DomainException(sprintf('%s::$name is of type %s, string expected', static::class, gettype($this->name)));
}
return $this->name;
}
}
class Goed extends Miauw
{
public function __construct()
{
$this->name = 'Yay!';
}
}
class Fout extends Miauw
{
public function __construct()
{
$this->name = 42;
}
}
try
{
$goed = new Goed();
var_dump($goed->getName());
$fout = new Fout();
echo $fout->getName();
}
catch (Exception $e)
{
var_dump($e->getMessage());
}
?>
abstract class Miauw
{
protected $name;
final public function getName() // Final!
{
if ( ! is_string($this->name))
{
throw new DomainException(sprintf('%s::$name is of type %s, string expected', static::class, gettype($this->name)));
}
return $this->name;
}
}
class Goed extends Miauw
{
public function __construct()
{
$this->name = 'Yay!';
}
}
class Fout extends Miauw
{
public function __construct()
{
$this->name = 42;
}
}
try
{
$goed = new Goed();
var_dump($goed->getName());
$fout = new Fout();
echo $fout->getName();
}
catch (Exception $e)
{
var_dump($e->getMessage());
}
?>
Toevoeging op 09/12/2013 11:23:41:
static::class werkt niet?
http://no1.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class.class
Voor PHP < 5.5 heb je get_class($this) nodig.
Voor PHP < 5.5 heb je get_class($this) nodig.
Ah oke. Deze werkt overigens ook: get_called_class() Geen idee wat het verschil is met get_class($this) ?
get_called_class() is beschikbaar vanaf PHP 5.3, de zelfde versie die namespaces introduceerde, dus je zit goed.
Edit: moest inderdaad get_called_class() zijn...
Gewijzigd op 09/12/2013 13:28:47 door Dos Moonen
Je bedoelt get_called_class?
Wat is trouwens beter, om een method te gebruiken, dus get_called_class()? Of zoals jij doet met static::class? En gaat het dan toevallig mis als je een class property met de naam $class hebt?
Gewijzigd op 09/12/2013 12:19:29 door Ozzie PHP
Nee, ::class is de syntax in PHP5.5 betekend dat je de FQCN krijgt. (zie ook php.net) Een property is static::$class
Ah zo, oké. Is dat dan een soort vervanging voor de magic constant __CLASS__ ?