![]() |
PHP getters i klasser, funkar det?
Jag har testat lite php för skoj skull och nyfikenhet. Ville se hur implementationen av objektorrientering ser ut i PHP.
Hittils är jag inte ett dugg impad, de exempel på klasser, metoder och object på php.net lämnar mycket ett önska. Hur som helst så testade jag hur det står till med getters och setters som finns i de flesta andra objektoerienterade programmeringsspråk. Setters fick jag att funka även om det ser väldigt oelegangt löst ut enligt syntaxen, men det funkar i alla fall. Men getters har jag inte lyckats få till. Hur tusan åstadkommer man det på ett bra sätt? Bifogar min testkod som kompilerar felfritt som den ser ut med version 5.3.15. Kod:
<?php |
Använd __get och __set
PHP har två så kallade magiska funktioner för att implementera getters och setters. De heter __get respektive __set och de tar emot värdets namn som argument.
Här är en snabb klass för att demonstrera det hela. Kod:
class Person Kod:
class Person Kod:
$person = new Person(); |
public string function _get_firstName() => public function _get_firstName()
|
Nu har jag testat vidare och får ett nasty felkod på 255 som jag inte inser vad det är. Har ingen riktig IDE utan kör med Textpad som editor.
La till felhantering i get och set så man fångar upp felaktiga propertynamn. Kod:
<?php |
Vad får du för felmeddelande?
|
Om du skriver korrekta kommentarer och lägger till det kommatecken som saknas så ser det ut att fungera.
Kod:
<?php |
Nu har jag fått till det som jag vill ha det, ett tydligt felmeddelande när man använder odefinierade egenskaper på en klass (det borde vara inbyggt i ett objektorienterat språk):
Kod:
<?php |
Edit: äh, glöm det....
|
Edit: glöm det...
|
Nu vet jag inte vad du egentligen är ute efter men att behöva ange alla godkända egenskaper i __set och __get känns omständigt.
Jag skulle gjort såhär: http://pastebin.com/ZDzJM0NL Och för att lägga till nya egenskaper som ska kunna sättas definierar du först scopet och sen sätter dem till något defaultvärde i konstruktorn. |
Citat:
Det är en del av styrkan med att ha den objektorienterde paradigmen. Man ökar kvaliten på koden mångfalt genom att programspråket stöder denna princip. Jag har aldrig sett något annat sråk som tillåter odefinierade egenskaper i en klass. I enklare imperativa skriptspråk är det vanligt att ha odeklareade/dynamiska variabler, men i objektorienterade språk brukar det i vart fall finnas den implicita tvingande egenskapen (kanske 'restriktionen' på ren svenska). Att ha getters och setters är till för att man ska kunna ha beräknade egenskaper som ibland kan vara ganska komplexa. Men de ska vara enkla att använda. Man kan vidare ha validering av status på en egenskap genom att använda getters och setters, så man kan kasta en exception om det blir tokigheter. Det finns även situationer där man ha komplicerade formateringsregler av caption (dvs displayvärden) men man har fortfarande en ganska teknisk grundinformation, typexempel kan vara datum som kan vara lagrat som ett mycket kompakt lagringsformat men som visas med en text som är lätt för en människa att förstå. Andra exempel är "scientific notation" o.s.v. .... Det är kompilatorns styrka att den hjälper mig att hitta fel under utvecklingsarbetet, jag vill ALDRIG råka ut för att fel smyger med och upptäcks först i produktion. Det är ofta 100-1000 gånger dyrare att åtgärda fel som upptäcks i produktion jämfört med under kodningsfasen eller kravfasen. |
Jag har brutit ut den generella egenskapen att hantera getters och setetrs och lagt det i en abstract Rootklass så andra klasser kan ärva in beteendet och vissa egenskaper.
Så här blev det i min testkod: Kod:
<?php Kod:
<?php Kod:
<?php Kod:
<?php |
Citat:
Du behöver ju faktiskt inte använda dem och de har ett par nackdelar så som: - De är långsammare än direkt access eller access via en vanlig funktion - Det är svårare att skriva bra dokumentation för dem Den klassiska metoden är att skriva get/set metoder för varje värde du vill exponera och även den metoden jag rekommenderar även om det blir mer knackande på tangentbordet. Kod:
class Person |
Citat:
Jag menade att det känns som en dålig lösning att ha en switch-/if-sats i __get och __set. Min lösning visar ett sätt att slippa det. |
Citat:
Dummaste jag sett på länge.. Antingen kan du språket/vet vad du gör (oavsett programspråk) eller så kan/vet du inte.. Vad är det för mening med att sätta 200 parametrar som ändå inte används? PHP-kod:
Bygga in skydd/lager-på-lager-på-lager-på-lager mot klantskallar kan ju Java/.NET fortsätta hålla på med tills dom avlider.. Förväntar du dig ett viss datatyp när du sätter en property så får du väl kolla efter det istället? Inte bara om den ens finns "definierad" i klassen. |
Citat:
Din abstrakta klass verkar lite omständig. Med switch-satsen måste du uppdatera root-klassen med alla properties för alla underklasser. Du har redan fått ett vettigt exempel med isset() istället, som du faktiskt kan lägga som en abstrakt klass utan att få massa switch cases på ett helt ologiskt ställe. Använder du PHP5.4 kan du använda den som en trait (tyvärr är den inte helt redo för alla produktionsmiljöer pga extensions som apc och patches som suhoshin). Det finn en väl vedertagen standard för hur man skriver kommentarer för att kunna generera dokumentation i PHP - titta på phpdocumentor. Liksom för testning har du PHPUnit (allra mest välanvänt) som gör vad du gör i din testklass, fast smidigare, bättre output och enklare att integrera i byggservrar osv. Dynamiska properties är en styrka hos PHP. Överanvändning av det är en svaghet hos programmeraren. Med början i PHP5.4 finns det en stark anledning till att bli striktare med det då de har optimerat hanteringen av fördefinierade properties rejält. |
Citat:
Det är enligt mig självklart att man ska ha en switch/if i en get/set för att styra vad som händer, annars öppnar du ju upp klassen helt, och det kan ju inte vara tanken med get/set-metoderna. |
Citat:
Som jag uppfattade det var målet att det inte ska gå att sättaegenskaper som objektet inte redan har. Alla som finns ska kunna sättas/hämtas. |
Citat:
|
Citat:
Hämta egenskaper som inte finns, det går väl aldrig (dom finns ju inte?), och ifall man sätter en egenskap som inte finns egentligen så gör väl inte det så mycket? Håller med om att är "lite fult" såklart att kunna sätta egenskaper som inte finns egentligen, men klassen borde ju inte fråga efter den egenskapen ändå så borde inte påverka något, eller missar jag något? |
Citat:
|
Citat:
|
Jobbigt att skriva enhetstester för att täcka upp enkla slarvfel som kompilatorn snappar upp direkt tycker jag, därför jag håller mig till c# istället för php. Php har säkert en del styrkor och man ska nog inte försöka förändra dess natur genom att försöka få den att emulera ett mer strikt språk som Conny verkar vilja göra här.
|
Citat:
Kompilatorn fångar, av egen erfarenhet, upp fel som nybörjare ofta begår; syntax fel. Erfarna utvecklare missar sällan semikolon eller har ett mellanslag på fel ställe. Vi gör istället logiska fel, fel som inte en kompilator kan hitta. |
Citat:
Helst skulle jag önska att man kan deklarera: public class Person { // declataion of private variables private _firstname=""; private _lastname=""; // Jag skippar konstruktorn i detta exempel.... public __set_firstname($value) { $this->_firstname = $value; } public __get_firstname() { return $this->_firstname; } public __set_lastname($value) { $this->_lastname = $value; } public __get_lastname() { return $this->_lastname; } // Jag skippar även ToString-metoden.... } När man sen accessar egenskapen så vill jag göra så här: private $kalle = new Person(); $kalle.firstname = "Kalle"; $kalle.lastname = "Pettersson"; echo $kalle.firstname . " " . $kalle.lastname Resultatet ska då bli: "Kalle Pettersson" OBSERVERA att det inte alls är samma sak som att ha en funktion som geter getFirstName och en funktion som heter setFirstName, det är INTE getters och setters.... Ni som har jobbat med andra objektorienterade språk vet nog vad jag menar... . . . |
Citat:
Om du inte begriper objektorienterad programmering så bör du inte komma med fullkomligt idiotiska inlägg här i forumet. |
Citat:
Dvs exempelvis som i C# där man kan ha en metod för att validera värden när de sätts till en metod, 'är värdet utan för det giltigas gräns så kan man endera låta bli att lagra värdet i klassen eller göra en Throw Exception("Med ett vettigt felmeddelande").... När man läser av ett värde så kan man exempelvis ha en automatisk konvertering, formatering, lagring av accessstatistik eller inläsning från någon extern källa. detta utan att programmeraren som använder egenskapen behöver bekymra sig över hur det går till. |
Citat:
Kompilatorn fångar upp just stavfel eftersom den upptäcker att du inte deklarerat den felstavade variabeln och du får ett felmeddelande som talar om exakt vilken variabel, konstant funktion, klass eller annan identifierare som du stavat fel på samt exakt vilken rad och kolumn där felet börjar. Kompilatorn hittar många enkla fel och underlättar programmerarens arbete enormt på den punkten. Några saker som kompilatorn gör enträget: - Kollar syntax - Kollar att alla variabler som används i programmet är deklarerade - Kollar att alla variabler som är deklarerade används, annars får man en varning - Kollar att alla uttryck som tilldelar en variabel har rätt datatyp (dvs den deklarerade datatypen) - Kollar att alla satser i programmet är avslutade - kollar att alla kodblock är definierade med start och slut - Kollar att identifierarnas scope stämmer . . . Kompilatorn är programmerarens bästa vän... Jag har mycket svårt att acceptera att det fortfarande finns programspråk som saknar kompilator.... De som ligger bakom php har tydligen fått en hel del önskemål från mer erfarna utvecklare om att tighta tillk språket så man får ett något bättre stöd för typning och deklarationer, men jag tycker de hittils gjort det lite till en halvmesyr. Mitt försök är till för att försöka lära mig om det finns möjligheer att strama till språket för att få bättre felhantering redan innan koden tas i produktion. |
Så här skulle motsvarande program se ut i C# med de metoder och properties jag var ute efter:
Kod:
using System; Kod:
using System; Kod:
using System; Kod:
Visa alla Person i personer... |
Efter att ha testkört koden under Ubuntu 12.04 med mono-mcs (en C# clone i Linux-miljön) så kan jag konstatera att resultatet av testkörningen blev identiskt med Windows 7.
Jag bifogar Makefile för den som vill testa: Kod:
################################################################# |
Citat:
Du vet inte hur PHP (eller dess objekthantering) fungerar så hur skulle du kunna förstå vad jag menade.. Jag begriper däremot inte varför du ens ger dig på att försöka använda PHP, du är så inställd på hur typade och kompilerade språk fungerar och måste jämföra allt med dessa hela tiden. |
Citat:
Att inte kunna identifiera oanvändna egenskaper eller metoder är en nackdel i språket. Det är såpass svårt just pga dess dynamiska natur. Enda sättet att komma runt detta är att göra alldeles för omfattande tester där du kan vara säker på 100% av använd kod exekveras (och det är knappats något som man brukar göra i några projekt även om vissa läroböcker säger det). Kollar att satser är avslutade gör du enkelt med en Linter redan medans du skriver. Du har även andra bra verktyg du kan använda i det stadiet för att kontrollera koding-standard, komplexitet osv (se t ex PHPCS, PHP MD). Notera att du även har en PHPCS feature där du kan fixa din kod (PHPCS fixer) så den inte behöver se ut som maskerad C#. För ditt exempel. Om du vill ha setters och getters för varje variabel som ska accessas utifrån är det bara att du i get/set kollar efter funktionsnamnet och anropar den om den finns. Desto snyggare än switch/if som väldigt lätt introducerar fel (speciellt en miss av en break; som du förmodligen inte upptäcker ens med din kompilator). Om du vill titta på vad ett språk du inte är van vid har för möjligheter att göra något du vill göra får du först titta på vad du vill göra och vilka effekter det ska ha. I nästa skede tittar du på hur du kan åstakomma det i valda språket. Att börja med hur du gör det i ett annat språk är fel väg att gå oavsett vilket språk du kommer till. Skriv i språket du använder, annars gör du bättre i att hålla dig till C#. Det som PHP Core har att ta ställning till är hur de ska behålla det de byggt. De har byggt ett språk utan stark kommersiell backning som nu används av hälften av de 40 största webbsajterna (motsvarande för .NET är runt 10%, och i stort sett uteslutande microsoft-sajter). Jag kan hålla med om att vissa saker har saknats för objektorienterad utveckling, men att det går fel väg framåt (försiktigt) eller att det är en halvmesyr håller jag inte med om. Att göra det till ett stelt kompilerat språk skulle vara ett bra sätt att döda språket på ett par år. Det skulle bli ett snabbare, stelare och bok-"korrekt" språk - som 75% av användarna övergav. |
Alla tider är GMT +2. Klockan är nu 20:20. |
Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson