Kom ihåg mig?
Home Menu

Menu


PHP getters i klasser, funkar det?

 
 
Ämnesverktyg Visningsalternativ
Gammal 2012-07-24, 01:34 #1
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
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
class Person
{
    private $firstname;
    private $lastname;

	public function __construct($pFirstname, $pLastname)
	{
		$this->firstname = $pFirstname;
		$this->lastname = $pLastname;
	}

    public function __set($name, $value)
    {
        switch ($name)
        {
            case 'firstname':
                $this->firstname = $value;
                break;

            case 'lastname':
                $this->lastname = $value;
                break;

            default:
            		# By throwing Exception for undefined property we can enforce strict property definition rules
            		# we also achive better error messages for improved debugging during development
            		# this is necessary because of lack of support for strict properties in php 5.3.15
            		$error = "Error: __set property: " . $name . " not supported by class: " . __CLASS__ ;
					throw new Exception($error);
					break;
        }
    }

    public function __get($name)
    {
        switch ($name)
        {
            case 'firstname':
                return $this->firstname;
                break;

            case 'lastname':
                return $this->lastname;
                break;

            default:
            		# By throwing Exception for undefined property we can enforce strict property definition rules
            		# we also achive better error messages for improved debugging during development
            		# this is necessary because of lack of support for strict properties in php 5.3.15
            		$error = "Error: __get property: " . $name . " not supported by class: " . __CLASS__ . ".";
					throw new Exception($error);
					break;
        }
        return null;
    }

	/*
	* a String representation for all Persons.
	*/
	public function __toString()
	{
		return $this->firstname . " " . $this->lastname;
	}
}


?>

<?php

	$rad = 0;
	try
	{
		echo "\nTest of errormessage wehen faulty property ...\n";
		echo "(row) - Firstname Lastname\n";
		# create a PHP Array and initialize it with Person objects
		$persons = array
		(
			new Person("Fredrik", "Framberg"),
			new Person("Greta", "Gavelstam"),
			new Person("Urban", "Urberg"),
			new Person("Anna", "Ambtesteg"),
			new Person("Henrik", "Hammarberg"),
			new Person("Kristina", "Karlestam"),
			new Person("Hans", "Hallin"),
			new Person("Berit", "Bygdén")
		);

		# print out the results - calls Person->__toString().
		foreach($persons as $person) echo "(" . ++$rad . ") - " . "$person\n";
	}
	catch (Exception $e)
	{
		echo 'Caught exception (1): ',  $e->getMessage(), "\n";
	}

	try
	{
		echo "\nTest of creating new object of class Person ...\n";
		$faultyPerson = new Person("Dennis","Harper");
		echo "This message will hopefully be written to console.\n";
	}
	catch (Exception $e)
	{
		echo 'Caught exception (2): ',  $e->getMessage(), "\n";
	}

	try
	{
		echo "\nTest of errormessage when faulty __set property ...\n";
		echo "(" . ++$rad . ") - " . "$faultyPerson\n";
		$faultyPerson->Age = 34;
		$faultyPerson->ShoeSize = 45;
		echo "Age: " . $faultyPerson->Age . " years.\n";
		echo "ShoeSize: " . $faultyPerson->ShoeSize . ".\n";

		echo "This message will not be written to console.\n";

	}
	catch (Exception $e)
	{
		echo 'Caught exception (3): ',  $e->getMessage(), "\n";
	}

	try
	{
		echo "\nTest of errormessage when faulty __get property ...\n";
		echo "(" . ++$rad . ") - " . "$faultyPerson\n";
		echo "ShoeSize: " . $faultyPerson->ShoeSize . ".\n";
		echo "Age: " . $faultyPerson->Age . " years.\n";

		echo "This message will not be written to console.\n";

	}
	catch (Exception $e)
	{
		echo 'Caught exception (4): ',  $e->getMessage(), "\n";
	}

	echo "\nDone testing class: Person.\n---------------------------------------\n\n";
?>

Senast redigerad av Conny Westh den 2012-07-24 klockan 01:39
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-24, 10:57 #2
HenrikAI HenrikAI är inte uppkopplad
Flitig postare
 
Reg.datum: Nov 2004
Inlägg: 331
HenrikAI HenrikAI är inte uppkopplad
Flitig postare
 
Reg.datum: Nov 2004
Inlägg: 331
Edit: äh, glöm det....

Senast redigerad av HenrikAI den 2012-07-24 klockan 10:59
HenrikAI är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-24, 11:02 #3
HenrikAI HenrikAI är inte uppkopplad
Flitig postare
 
Reg.datum: Nov 2004
Inlägg: 331
HenrikAI HenrikAI är inte uppkopplad
Flitig postare
 
Reg.datum: Nov 2004
Inlägg: 331
Edit: glöm det...
HenrikAI är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-24, 13:21 #4
orreborres avatar
orreborre orreborre är inte uppkopplad
Flitig postare
 
Reg.datum: Apr 2003
Inlägg: 309
orreborre orreborre är inte uppkopplad
Flitig postare
orreborres avatar
 
Reg.datum: Apr 2003
Inlägg: 309
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.
orreborre är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-24, 20:35 #5
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Citat:
Ursprungligen postat av orreborre Visa inlägg
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.
Det är ju en rätt grundläggande princip att man alltid måste definiera en klass egenskaper i dess defnition, så att man INTE kan stoppa in nya egenskaper i en klass i runtime.

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.

Senast redigerad av Conny Westh den 2012-07-24 klockan 20:48
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-24, 22:28 #6
Weaver Weaver är inte uppkopplad
Flitig postare
 
Reg.datum: Aug 2006
Inlägg: 403
Weaver Weaver är inte uppkopplad
Flitig postare
 
Reg.datum: Aug 2006
Inlägg: 403
Citat:
Ursprungligen postat av ConnyWesth Visa inlägg
Jag har aldrig sett något annat sråk som tillåter odefinierade egenskaper i en klass.
Det är därför funktionerna __get/__set kallas för magiska Och magi är just oftast sådant vi vill undvika såvida det inte finns en annan lösning.

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
{
    private $firstname;

    public function getFirstname()
    {
        return $this->firstname;
    }

    public function setFirstname($firstname)
    {
       $this->firstname = $firstname;
    }
}
Weaver är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-25, 10:58 #7
orreborres avatar
orreborre orreborre är inte uppkopplad
Flitig postare
 
Reg.datum: Apr 2003
Inlägg: 309
orreborre orreborre är inte uppkopplad
Flitig postare
orreborres avatar
 
Reg.datum: Apr 2003
Inlägg: 309
Citat:
Ursprungligen postat av ConnyWesth Visa inlägg
Det är ju en rätt grundläggande princip att man alltid måste definiera en klass egenskaper i dess defnition, så att man INTE kan stoppa in nya egenskaper i en klass i runtime.

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.
Ja, du missuppfattade vad jag menade.
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.
orreborre är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-26, 12:06 #8
Ishras avatar
Ishra Ishra är inte uppkopplad
Nykomling
 
Reg.datum: Nov 2007
Inlägg: 25
Ishra Ishra är inte uppkopplad
Nykomling
Ishras avatar
 
Reg.datum: Nov 2007
Inlägg: 25
Citat:
Ursprungligen postat av orreborre Visa inlägg
Ja, du missuppfattade vad jag menade.
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.
Din lösning är inte speciellt bra, det enda du har åstadkommit är 20 extra rader för att göra alla klassens egenskaper till public eftersom man med din kod kommer åt alla private variabler, och ifall man gör det så kan man väl likagärna sätta dom till public direkt?

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.
Ishra är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-26, 15:42 #9
orreborres avatar
orreborre orreborre är inte uppkopplad
Flitig postare
 
Reg.datum: Apr 2003
Inlägg: 309
orreborre orreborre är inte uppkopplad
Flitig postare
orreborres avatar
 
Reg.datum: Apr 2003
Inlägg: 309
Citat:
Ursprungligen postat av Ishra Visa inlägg
Din lösning är inte speciellt bra, det enda du har åstadkommit är 20 extra rader för att göra alla klassens egenskaper till public eftersom man med din kod kommer åt alla private variabler, och ifall man gör det så kan man väl likagärna sätta dom till public direkt?

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.
Fast det beror ju på vad målet med det hela är.
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.
orreborre är inte uppkopplad   Svara med citatSvara med citat
Gammal 2012-07-31, 03:42 #10
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Citat:
Ursprungligen postat av orreborre Visa inlägg
Ja, du missuppfattade vad jag menade.
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.
Jag är alltså ute efter ett sätt att skapa getters och setters så man kan ha individuell kod fölr varje property, det är inte ett sätt att skriva mer krånglig kod. I andra programspråk somexempelvis C#, men även Visual Objects, VB.NET så kan man använda pegreppet "property" för att definiera en ndividuellt utformat kod, det är lite dte jag är ute efter. Men det gick inte att deklarera mer än en __get och en __set -metod per klass

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...


.
.
.

Senast redigerad av Conny Westh den 2012-07-31 klockan 03:46
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Svara


Aktiva användare som för närvarande tittar på det här ämnet: 1 (0 medlemmar och 1 gäster)
 

Regler för att posta
Du får inte posta nya ämnen
Du får inte posta svar
Du får inte posta bifogade filer
Du får inte redigera dina inlägg

BB-kod är
Smilies är
[IMG]-kod är
HTML-kod är av

Forumhopp


Alla tider är GMT +2. Klockan är nu 03:43.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson
 
Copyright © 2017