Variable van parrent class aanroepen
Code (php)
In dit geval vind ik PERSOONLIJK dat je de plank misslaat. Het voegt niks toe om properties via private functies te gaan setten. Het zorgt er alleen voor dat je code langer wordt (er moet meer code worden ingelezen) en dat alles trager wordt (er wordt 2x onnodig een method aangeroepen).
Ik zou het gewoon zo doen:
Code (php)
Precies hetzelfde resultaat.
Waarom ik private properties gebruik? Ik vind dat een class zelf zijn properties moet kunnen bepalen, controleren en beheren. Door een property public te maken, kun jij er alles van maken wat je wilt. Stel we hebben een property $name. Dit moet bijv. een string zijn van minimaal 3 tekens. Via een setter kan ik dit controleren. Op het moment dat ik een public property gebruik, kan dat niet. Sterker nog, ik kan er alles van maken wat ik wil:
$user->name = 12345;
$user->name = false;
$user->name = new stdClass();
enz.
KORTOM: je bent alle controle kwijt.
JA MAAR: je gaat zelf toch niet van die rare waardes invullen? Wat ben je dan voor een flut-programmeur?
Ha, goede vraag! Dat dacht ik dus ook! Maar het vervelende is dat jouw geheugen niet alles kan onthouden.
Stel we gaan een user instellen:
Mooi da's gefixt. Je gaat vrolijk verder met programmeren. 2 Dagen later is je pagina af en valt je ineens op dat jouw naam niet in beeld verschijnt. Wat is er gebeurd? Je hebt weliswaar keurig de naam toegekend aan de user, maar je was vergeten dat de User class helemaal geen gebruikmaakt van de property $name. Wat je had moeten doen is dit:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$user = new User();
$user->first_name = 'Ger';
$user->last_name = 'van Steenderen';
?>
$user = new User();
$user->first_name = 'Ger';
$user->last_name = 'van Steenderen';
?>
Omdat je de properties hebt toegekend als publieke properties, krijg je geen foutmelding. De code werkte dus gewoon, maar deed niet wat jij verwachtte.
Oké, nog één laatste voorbeeldje dan. Je hebt een of andere klanten-cms class. Op een mooie dag besluit je dat die klanten-cms class nog een aantal config settings nodig heeft. Mooi, dan voeg je dus gewoon een 'config' property toe aan de client_cms class.
Code (php)
1
2
3
2
3
<?php
$clients_cms->config = array('type' => $foo_type, 'layout_type' => 'ger_cms');
?>
$clients_cms->config = array('type' => $foo_type, 'layout_type' => 'ger_cms');
?>
Mooi da's gefixt. De volgende ochtend zit je mailbox vol met mailtjes van boze klanten. Hun cms werkt niet meer. Tja, wist jij veel dat je een bestaande config property had overschreven waarin alle cms settings waren opgeslagen????
KORTOM: voorkom vervelende situaties en maak het jezelf makkelijker door je properties af te schermen voor de buitenwereld en gewoon simpelweg nooit met public properties te werken. Vergelijk het eens met een electrisch apparaat (bijv. je telefoon). De fabrikant garandeert een juiste werking zolang jij het apparaat dicht laat zitten en niet openmaakt. Op het moment dat je het apparaat openmaakt (je properties public maakt) kan een juiste werking niet meer gewaarborgd worden (en vervalt je garantie).
Gewijzigd op 13/06/2013 00:30:13 door Ozzie PHP
Nou laat ik vooropstellen dat ik ermee eens ben dat (in scripttalen) public properties daar waar mogelijk vermeden moeten worden, echter vind ik een nooit niet op zijn plaats, er kunnen situaties voorkomen dat je niet zonder kan. Neem nu PDO fetch object, dan worden de properties on the fly gegenereerd en dus zijn ze public.
Ook dan is het geen public gebruiken. Ofwel via een magic getter __get( $name ), ofwel via een algemene getter get( $name )
De reden dat ik wel degelijk keihard 'nooit' zeg is omdat ik van geen enkele situate weet waarin een public property een voordeel heeft boven een private property. Andersom zijn er meerdere.
Disclaimer: het enige voordeel dat ik me kan bedenken, maar negeer, is het performance voordeel omdat je niet een extra functie hoeft aan te roepen.
Gewijzigd op 15/06/2013 11:25:07 door Erwin H
Toevoeging op 15/06/2013 11:39:06:
"Nou laat ik vooropstellen dat ik ermee eens ben dat (in scripttalen) public properties daar waar mogelijk vermeden moeten worden."
Ook in een magic getter kan je nog een test zetten en bepalen wat er gedaan wordt. Dus ook met een magic getter heb je nog volledige controle over wat er met de properties gedaan wordt. Welke gelezen mogen worden en welke er geschreven mogen worden. Maak je het een public property dan is dat niet het geval.
Toevoeging op 15/06/2013 11:41:29:
Ger van Steenderen op 15/06/2013 11:32:52:
"Nou laat ik vooropstellen dat ik ermee eens ben dat (in scripttalen) public properties daar waar mogelijk vermeden moeten worden."
Laat ik vooropstellen dat ik altijd zal zeggen dat je nooit public properties moet gebruiken en dat ik nog steeds, van niemand, een serieus, onweerlegbaar argument heb gehoord wat mij aan het twijfelen heeft gebracht over deze absolute waarheid.
Gewijzigd op 15/06/2013 11:42:55 door Erwin H
Gewijzigd op 15/06/2013 12:26:00 door Wouter J
@Erwin
Ik haalde bewust het voorbeeld van PDO fetch object aan, omdat ik daarvan weet dat daarvan in ieder geval de properties vanuit de database public zijn (lezen/schrijven).
Een keuze die je als programmeur zou kunnen maken, want dan leg je de verantwoordelijkheid van de inhoud bij die andere programmeur die jouw object gebruikt.
Dat jij het met die keuze niet eens bent is een ander verhaal.
Eigenlijk vind ik dat ingaan tegen mijn/de OOP principes. In mijn ogen is het onjuist om de verantwoordelijkheid van hoe een object gebruikt kan worden bij een niet bekende programmeur te leggen. Objecten dienen zelfstandig te zijn en zelf verantwoordelijk te zijn voor hoe ze gebruikt kunnen worden.
Maar goed, er zijn vast wel meer voorbeelden te bedenken waarin public properties gebruikt worden. Ik zal dat echter nooit doen, totdat iemand mij eindelijk eens kan overtuigen van een goed argument om dat wel te doen.
Ik wilde alleen maar aangeven dat er altijd uitzonderingen zijn die de regel bevestigen.
Over de eerste ben ik wel benieuwd hoe je er dan gebruik van maakt? En dan voornamelijk, maak je er op een dusdanige manier gebruik van dat als het niet als public property zou zijn geimplementeerd, maar via bijvoorbeeld een magic getter, dat je dan niet meer zou kunnen wat je er nu mee doet? In dat geval zou er namelijk mogelijk een reden zijn om af en toe wel public properties te gebruiken....
Ik werk op het moment aan project in CodeIgniter, en de fetch van de CI database class geeft standaard een object terug, ik heb gezien in de code dat gewoon 1 op 1 het object is wat je krijgt met PDO fetch object.
En dan zijn de kolomnamen de properties (bv $row->product_name), en daaruit concludeer ik dat ze on the fly gegenereerd worden, en zijn ze dus automatisch public.
Nu heb ik in mijn model een paar queries met een paar group_concats daarin, en voordat ik het resultaat terug geef aan de controller zet ik die string om in een array:
Gewijzigd op 16/06/2013 20:27:00 door Ger van Steenderen