Door
Jan R
op 26-12-2020 19:30
gewijzigd op 26-12-2020 19:36
2.413 views
Gewone gegevens in een class zoals bool en int forceren als type kan sinds php 7.4
zoals hier
<?
class cSpeler{
public string $Name='';
public string $Remarq='';
//public $Adres;
}
class cAdres {
public string straat='';
public string huisnummer='';
}
?>
Hoe kan ik echter adres forceren als type cAdres?
Hoe kan ik een array van type Bool of int forceren?
<?php
class cSpeler
{
public string $Name = '';
public string $Remarq = '';
public cAdres $Adres;
}
class cAdres
{
public string $straat = '';
public string $huisnummer = '';
}
?>
Ik ben alleen niet zo gecharmeerd van lege strings '' als geldige waarde voor vereiste data. Maak die liever nullable als ze mogen ontbreken.
Voor een parameter die null mag zijn zet je een vraagteken voor het datatype:
<?php
class cSpeler
{
public ?string $Name = null;
public ?string $Remarq = null;
public ?cAdres $Adres = null;
}
class cAdres
{
public ?string $straat = null;
public ?string $huisnummer = null;
}
?>
Als een array een vaste structuur heeft, dan zou ik er een value object van maken of, afhankelijk van het gewenste gedrag. bijvoorbeeld een stack, heap of queue.
in mijn class heb ik meerdere X van Y voorbeeld in de classe spelers heb ik meerdere spelers;
Voor spelers heb ik al een subclasse. ik wil dus in mijn bestaande classe een array invoeren van classe spelers.
voorbeeld
<?php
class clsxmt{
public float $version=3.2;
public int $AantalSpelers;
public string $Name;
public array $Speler;
public array $MarkedGames;
}
class CMarkedGame {
public int $x;
public int $y;
public int $color;
}
class cSpeler{
public string $Name='';
public clsAdvantage $Advantage;
public string $StamNummer='';
public string $Elo='';
public string $Remarq='';
public $Punten = array();
public $Remarqs = array();
public function __construct(){
$this->Advantage = new clsAdvantage;
}
public int $UniekNR;
}
class clsAdvantage{
public float $Punten=0;
public float $WeerstandsPunten=0;
public float $WinstPunten=0;
}
?>
Speler = array van type cSpeler
MarkedGames = array van CMarkedGame
Punten = array van string lengte 1
Remarqs = array van string lengte onbekend
Een PHP-array heeft een relatief vrije vorm: de sleutel is altijd een integer of een string, en de waarde kan van elk datatype zijn.
Wil je een array een striktere vorm geven, dan doe je dat niet in de array zelf, maar in de methode die de array opbouwt of vult. Daartoe kun je een klasse definiëren die zich als een array gedraagt door ArrayObject te extenden of ArrayAccess te implementeren.
public function addChild(Child $child) {
$this->children[] = $child;
return $this;
}
public function getChildren() {
return $this->children;
}
}
$master = new Master();
$child = new Child();
$child->setName('Jan');
$master->addChild($child);
$child = new Child();
$child->setName('Miep');
$master->addChild($child);
foreach($master->getChildren() as $child)
{
echo $child->getName() . "\n";
}
?>
[size=xsmall]Toevoeging op 04/01/2021 09:30:38:[/size]
p.s. Waar het pas interessant gaat worden is als je een functie removeChild() wilt toevoegen.
$children is in bovengenoemd voorbeeld een numerieke array. Je kan dan removeChild($key) doen maar dat is helemaal niet gebruiksvriendelijk. Als je immers de key van de array niet weet moet je dat als "gebruiker" van de class zelf gaan uitvogelen. In C++ kun je operators van de class overschrijven zodat je invloed kunt uitoefenen op het vergelijken van objecten of kopiëren van objecten. Dat kan in php helaas niet. Wel kun je aan de Child class een vergelijk functie toevoegen:
<?php
public static function compare(&$child1, &$child2)
{
if ($child1->name != $child2->name)
return 0;
return 1;
}
?>
Bovenstaande zou je nog beter doen door een abstracte class te schrijven met een naam als Comparable maar dat gaat misschien op dit moment wat ver..
Realiseer je ook dat je voor een goede vergelijking een unieke identifier nodig hebt. Het voorbeeld van mij voorziet hier niet in want als twee Children dezelfde $name hebben dan gaat het mis. Een unique identifier (of unique id) kan ook uit meerdere properties van de class bestaan.
Als je met zo'n externe identifier via de interne structuur van parent directe toegang nodig hebt tot één individueel child, deugt je ontwerp waarschijnlijk niet. Vermoedelijk heb je dan functionaliteit met een eigen verantwoordelijkheid die je moet afsplitsen naar een aparte class; de parent is dan meer een container die je als traversable met een foreach doorloopt.
Hoi Ward ik weet niet of ik je helemaal kan volgen of dat we op één lijn zitten maar Als je een numerieke array hebt met meerdere elementen en je wilt er één element uithalen dan zul je op een of andere manier moeten bepalen welke dat gaat worden. (Tenzij je weet welke key het is van de array maar dat laat ik even buiten beschouwing). Dat iedere class zijn eigen verantwoordelijkheid moet hebben is mij duidelijk.
Waar ik aan dacht is:
<?php
// masterclass
public function removeChild(Child $child)
{
foreach ($this->children as $k => $c) {
if(Child::compare($child, $c)) {
unset($this->children[$k]);
return true;
}
}
return false;
}
?>
De verantwoordelijkheid of twee Childs hetzelfde zijn of niet ligt bij de Child class. Er is ook een manier zonder compare functie middels Reflection maar dat is omslachtig en heeft ook nadelen.
Het was meer een algemene observatie Frank: nooit een operatie uitvoeren met iets binnen een class dat niet vanzelfsprekend tot de taak van die class hoort.
Bij een numerieke array zou ik in plaats van een interne oplopende integer de globaal unieke spl_object_id() gebruiken:
<?php
class MasterClass
{
private array $children = [];
public function addChild(Child $child): void
{
$this->children[spl_object_id($child)] = $child;
}
public function removeChild(Child $child): bool
{
$key = spl_object_id($child);
if (array_key_exists($key, $this->children)) {
unset($this->children[$key]);
return true;
}
return false;
}
}
?>
Bestaat het gevaar dat je array letterlijk of figuurlijk een dubbele Jan Jansen bevat, voor vader en zoon bijvoorbeeld? Dan heb je dat probleem ook al buiten de array en vervolgens bij het opbouwen van de array voor de class: het is daarom geen probleem dat je in/met de class moet oplossen, want dan ben je te laat.