WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   PHP getters i klasser, funkar det? (https://www.wn.se/forum/showthread.php?t=1054260)

Conny Westh 2012-07-23 01:51

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
 class Person
 {
  private $_firsName="";
  private $_lastName="";

  public function __construct($pFirstName, $pLastName)
  {
    $this->_firstName = $pFirstName;
    $this->_lastName = $pLastName;
  }

        /* property setters */
        /*
        * The setters works as expected....
        */
        public function _set_firstName($value)
        {
                  $this->_firstName = $value;
        }
        public function _set_lastName($value)
        {
                  $this->_lastName = $value;
        }


        /* property getters */
        /*
        * The getters DON'T work as expected....
        * Get errorcode 255 with no further explanation.
        * Dont find any information about getters in documentation
        */
        /*
        * public string function _get_firstName()
        * {
          *        return $this->_firstName;
        * }
        * public string function _get_lastName()
        * {
          *        return $this->_lastName;
        * }

        */
  /*
    * a String representation for all Persons.
    */
        public function __toString()
        {
                return "Firstname: $this->_firstName , Lastname: $this->_lastName";
        }
}


?>

<?php
        # create a PHP Array and initialize it with Person objects
        $persons = array
        (
                new Person("Fredrik", "Hammarberg"),
                new Person("Greta", "Karlestam"),
                new Person("Urban", "Hallin"),
                new Person("Anna", "Bygdén")
        );

        # print out the results - calls Person->__toString().
        foreach($persons as $person) echo "$person<br>\n";
?>


Weaver 2012-07-23 02:42

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
{
    public function __set($name, $value)
    {
        switch ($name)
        {
            case 'firstname':
                $this->firstname = $value;
                break;
           
            case 'lastname':
                $this->lastname = $value;
                break;
        }
    }
   
    public function __get($name)
    {
        switch ($name)
        {
            case 'firstname':
                return $this->firstname;
           
            case 'lastname':
                return $this->lastname;
        }
       
        return null;
    }
   
    private $firstname;
    private $lastname;
}

Här är en alternativ implementation som istället använder en array för att lagra värdena:
Kod:

class Person
{
    public function __set($name, $value)
    {
        $this->name[$name] = $value;
    }
   
    public function __get($name)
    {
        if (isset($this->name[$name])) {
            return $this->name[$name];
        }
       
        return null;
    }

    private $name = array();
}

Och här kommer ett användningsfall:
Kod:

$person = new Person();
$person->firstname = 'Conny';
$person->lastname = 'Westh';

echo "{$person->firstname} {$person->lastname}";

Hoppas det hjälper dig!

HenrikAI 2012-07-23 10:03

public string function _get_firstName() => public function _get_firstName()

Conny Westh 2012-07-23 19:50

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
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 necessare 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 necessare 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 "Firstname: $this->firstname , Lastname: $this->lastname";
        }
}


?>

<?php


        try
        {
                # 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 "$person<br>\n";
        }
        catch (Exception $e)
        {
                echo 'Caught exception: ',  $e->getMessage(), "\n";
        }

?>


Weaver 2012-07-23 20:46

Vad får du för felmeddelande?

jonny 2012-07-23 20:50

Om du skriver korrekta kommentarer och lägger till det kommatecken som saknas så ser det ut att fungera.

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 necessare 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 necessare 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 "Firstname: $this->firstname , Lastname: $this->lastname";
        }
}


?>

<?php


        try
        {
                # 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 "$person<br>\n";
        }
        catch (Exception $e)
        {
                echo 'Caught exception: ',  $e->getMessage(), "\n";
        }

?>


Conny Westh 2012-07-24 00:34

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";
?>


HenrikAI 2012-07-24 09:57

Edit: äh, glöm det....

HenrikAI 2012-07-24 10:02

Edit: glöm det...

orreborre 2012-07-24 12:21

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.

Conny Westh 2012-07-24 19:35

Citat:

Ursprungligen postat av orreborre (Inlägg 20445605)
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.

Conny Westh 2012-07-24 19:57

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
///////////////////////////////////////////////////////////////////////////////
// File: AbstractRoot.php
// Class: AbstractRoot
///////////////////////////////////////////////////////////////////////////////
abstract class AbstractRoot
{
    private $_ChildClassname;

        public function __construct($ChildClassname)
        {
                $this->ChildClassname = $ChildClassname;
        }

    public function __set($name, $value)
    {
        switch ($name)
        {
            case 'ChildClassname':
                $this->_ChildClassname = $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 necessare because of lack of support for strict properties in php 5.3.15
                            $error = "Error: __set property: " . $name . " not supported by class: " . $this->ChildClassname . "." ;
                                        throw new Exception($error);
                                        break;
        }
    }

    public function __get($name)
    {
        switch ($name)
        {
            case 'ChildClassname':
                return $this->_ChildClassname;
                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 necessare because of lack of support for strict properties in php 5.3.15
                            $error = "Error: __get property: " . $name . " not supported by class: " . $this->ChildClassname . ".";
                                        throw new Exception($error);
                                        break;
        }
        return null;
    }
}

?>

Kod:

<?php
///////////////////////////////////////////////////////////////////////////////
// File: Person.php
// Class: Person
///////////////////////////////////////////////////////////////////////////////
class Person extends AbstractRoot
{
    private $firstname;
    private $lastname;

        public function __construct($pFirstname, $pLastname)
        {
                parent::__construct(__CLASS__);

                // Always
                $this->firstname = $pFirstname;
                $this->lastname = $pLastname;
        }

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

Kod:

<?php
///////////////////////////////////////////////////////////////////////////////
// File: PersonAge.php
// Class: PersonAge
///////////////////////////////////////////////////////////////////////////////
class PersonAge extends AbstractRoot
{
    private $firstname;
    private $lastname;
    private $age;

        public function __construct($pFirstname, $pLastname, $pAge)
        {
                parent::__construct(__CLASS__);

                // Always
                $this->firstname = $pFirstname;
                $this->lastname = $pLastname;
                $this->age = $pAge;
        }

        /* a String representation for every PersonAge. */
        public function __toString()
        {
                return $this->firstname . " " . $this->lastname . " (" . $this->age . ")";
        }
}
?>

Kod:

<?php
///////////////////////////////////////////////////////////////////////////////
// File: PropertiesTest.php
// Test for Class: AbstractRoot, Person, PersonAge
///////////////////////////////////////////////////////////////////////////////
class PropertiesTest
{
        public function __construct()
        {
                try
                {
                        echo "\nTest of errormessage wehen faulty property ...\n";
                        echo "\nStart testing class: Person.\n---------------------------------------\n\n";
                        $rad = 0;

                        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";

                echo "\nStart testing class: PersonAge.\n---------------------------------------\n\n";
                try
                {
                        echo "\nTest of errormessage when faulty __set property ...\n";
                        $faultyPersonAge = new PersonAge("Arthur","Trent",47);
                        echo "(" . ++$rad . ") - " . "$faultyPersonAge\n";
                        $faultyPersonAge->age = 58;
                        $faultyPersonAge->ShoeSize = 43;
                        echo "ShoeSize: " . $faultyPersonAge->ShoeSize . ".\n";
                        echo "Age: " . $faultyPersonAge->age . " years.\n";

                        echo "This message will not be written to console.\n";
                }
                catch (Exception $e)
                {
                        echo 'Caught exception (5): ',  $e->getMessage(), "\n";
                }

                try
                {
                        echo "\nTest of errormessage when faulty __get property ...\n";
                        //$faultyPersonAge = new PersonAge("Gary","Middleton",56);
                        echo "(" . ++$rad . ") - " . "$faultyPersonAge\n";
                        echo "Age: " . $faultyPersonAge->age . " years.\n";
                        echo "ShoeSize: " . $faultyPersonAge->ShoeSize . ".\n";

                        echo "This message will not be written to console.\n";
                }
                catch (Exception $e)
                {
                        echo 'Caught exception (6): ',  $e->getMessage(), "\n";
                }

                echo "\nDone testing class: PersonAge.\n---------------------------------------\n\n";
        }
}

try
{
        $test = new PropertiesTest();
}
catch (Exception $e)
{
        echo 'Caught exception (7): ',  $e->getMessage(), "\n";
}

?>


Weaver 2012-07-24 21:28

Citat:

Ursprungligen postat av ConnyWesth (Inlägg 20445627)
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;
    }
}


orreborre 2012-07-25 09:58

Citat:

Ursprungligen postat av ConnyWesth (Inlägg 20445627)
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.

Jake.Nu 2012-07-26 01:34

Citat:

Ursprungligen postat av ConnyWesth (Inlägg 20445628)
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
///////////////////////////////////////////////////////////////////////////////
// File: AbstractRoot.php
// Class: AbstractRoot
///////////////////////////////////////////////////////////////////////////////
abstract class AbstractRoot
{
    private $_ChildClassname;

        public function __construct($ChildClassname)
        {
                $this->ChildClassname = $ChildClassname;
        }

    public function __set($name, $value)
    {
        switch ($name)
        {
            case 'ChildClassname':
                $this->_ChildClassname = $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 necessare because of lack of support for strict properties in php 5.3.15
                            $error = "Error: __set property: " . $name . " not supported by class: " . $this->ChildClassname . "." ;
                                        throw new Exception($error);
                                        break;
        }
    }

    public function __get($name)
    {
        switch ($name)
        {
            case 'ChildClassname':
                return $this->_ChildClassname;
                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 necessare because of lack of support for strict properties in php 5.3.15
                            $error = "Error: __get property: " . $name . " not supported by class: " . $this->ChildClassname . ".";
                                        throw new Exception($error);
                                        break;
        }
        return null;
    }
}

?>

Kod:

<?php
///////////////////////////////////////////////////////////////////////////////
// File: Person.php
// Class: Person
///////////////////////////////////////////////////////////////////////////////
class Person extends AbstractRoot
{
    private $firstname;
    private $lastname;

        public function __construct($pFirstname, $pLastname)
        {
                parent::__construct(__CLASS__);

                // Always
                $this->firstname = $pFirstname;
                $this->lastname = $pLastname;
        }

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

Kod:

<?php
///////////////////////////////////////////////////////////////////////////////
// File: PersonAge.php
// Class: PersonAge
///////////////////////////////////////////////////////////////////////////////
class PersonAge extends AbstractRoot
{
    private $firstname;
    private $lastname;
    private $age;

        public function __construct($pFirstname, $pLastname, $pAge)
        {
                parent::__construct(__CLASS__);

                // Always
                $this->firstname = $pFirstname;
                $this->lastname = $pLastname;
                $this->age = $pAge;
        }

        /* a String representation for every PersonAge. */
        public function __toString()
        {
                return $this->firstname . " " . $this->lastname . " (" . $this->age . ")";
        }
}
?>

Kod:

<?php
///////////////////////////////////////////////////////////////////////////////
// File: PropertiesTest.php
// Test for Class: AbstractRoot, Person, PersonAge
///////////////////////////////////////////////////////////////////////////////
class PropertiesTest
{
        public function __construct()
        {
                try
                {
                        echo "\nTest of errormessage wehen faulty property ...\n";
                        echo "\nStart testing class: Person.\n---------------------------------------\n\n";
                        $rad = 0;

                        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";

                echo "\nStart testing class: PersonAge.\n---------------------------------------\n\n";
                try
                {
                        echo "\nTest of errormessage when faulty __set property ...\n";
                        $faultyPersonAge = new PersonAge("Arthur","Trent",47);
                        echo "(" . ++$rad . ") - " . "$faultyPersonAge\n";
                        $faultyPersonAge->age = 58;
                        $faultyPersonAge->ShoeSize = 43;
                        echo "ShoeSize: " . $faultyPersonAge->ShoeSize . ".\n";
                        echo "Age: " . $faultyPersonAge->age . " years.\n";

                        echo "This message will not be written to console.\n";
                }
                catch (Exception $e)
                {
                        echo 'Caught exception (5): ',  $e->getMessage(), "\n";
                }

                try
                {
                        echo "\nTest of errormessage when faulty __get property ...\n";
                        //$faultyPersonAge = new PersonAge("Gary","Middleton",56);
                        echo "(" . ++$rad . ") - " . "$faultyPersonAge\n";
                        echo "Age: " . $faultyPersonAge->age . " years.\n";
                        echo "ShoeSize: " . $faultyPersonAge->ShoeSize . ".\n";

                        echo "This message will not be written to console.\n";
                }
                catch (Exception $e)
                {
                        echo 'Caught exception (6): ',  $e->getMessage(), "\n";
                }

                echo "\nDone testing class: PersonAge.\n---------------------------------------\n\n";
        }
}

try
{
        $test = new PropertiesTest();
}
catch (Exception $e)
{
        echo 'Caught exception (7): ',  $e->getMessage(), "\n";
}

?>



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:

// styrkan i PHP:
$x = new StdClass();
$x->pelle "ett namn";

// bara dumt!
eval($x->jagtrorjaghittarpanagotsomkanskeintefinnsmendetfunkarsakerteftersomphparjusakassochkontrollavindataharjusakertintemeddettaattgora); 

??

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.

Clarence 2012-07-26 09:09

Citat:

Ursprungligen postat av ConnyWesth (Inlägg 20445628)
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.

Ett par kommentarer:
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.

Ishra 2012-07-26 11:06

Citat:

Ursprungligen postat av orreborre (Inlägg 20445659)
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.

orreborre 2012-07-26 14:42

Citat:

Ursprungligen postat av Ishra (Inlägg 20445727)
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.

Nerix 2012-07-27 13:51

Citat:

Ursprungligen postat av ConnyWesth (Inlägg 20445627)
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.

Har du aldrig hört talas om metaprogrammering?

Ishra 2012-07-27 16:16

Citat:

Ursprungligen postat av orreborre (Inlägg 20445739)
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.

Ja, om det är syftet så gör ju din kod det den ska, tycker väl ändå att det är lite onödigt kanske, men den kritiken kan jag inte rikta mot din kod :=)

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?

goose 2012-07-28 22:24

Citat:

Ursprungligen postat av Ishra (Inlägg 20445809)

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?

handlar väl om att det kan bli en bugg om man råkar stava en property fel av misstag. i ett kontrollerande språk får man ett felmeddelande direkt av kompilatorn, men i php så skapas en ny property med en felstavad property och man måste jaga buggen.

Nerix 2012-07-29 11:38

Citat:

Ursprungligen postat av goose (Inlägg 20445864)
handlar väl om att det kan bli en bugg om man råkar stava en property fel av misstag. i ett kontrollerande språk får man ett felmeddelande direkt av kompilatorn, men i php så skapas en ny property med en felstavad property och man måste jaga buggen.

Ja, eller så ser man till och skriva ordentliga tester enligt BDD eller TDD.

goose 2012-07-30 00:57

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.

Nerix 2012-07-30 01:59

Citat:

Ursprungligen postat av goose (Inlägg 20445933)
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.

Tror inte riktigt jag hänger med. Hur skulle en kompilator se att du använt fel metodnamn? Jag menar, du skriver ett test som gör det möjligt att te.x skriva och läsa ett namn-attribut i en user-klass. Skulle du stava fel här så finns det ingen kompilator som säger till.

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.

Conny Westh 2012-07-31 02:42

Citat:

Ursprungligen postat av orreborre (Inlägg 20445659)
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...


.
.
.

Conny Westh 2012-07-31 02:52

Citat:

Ursprungligen postat av Jake.Nu (Inlägg 20445720)
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:

// styrkan i PHP:
$x = new StdClass();
$x->pelle "ett namn";

// bara dumt!
eval($x->jagtrorjaghittarpanagotsomkanskeintefinnsmendetfunkarsakerteftersomphparjusakassochkontrollavindataharjusakertintemeddettaattgora); 

??

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.

Du visar ju prov på att inte förstå programmeringens grunder över huvud taget, så dina kommentarer behöver ingen ens fundera på.

Om du inte begriper objektorienterad programmering så bör du inte komma med fullkomligt idiotiska inlägg här i forumet.

Conny Westh 2012-07-31 03:00

Citat:

Ursprungligen postat av orreborre (Inlägg 20445739)
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.

Det var ett av målet, just pga brister i php, men den huvudsakliga anledningen är att ha getters och setters som man kan sätta i andra objektorienterade språk.

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.

Conny Westh 2012-07-31 03:15

Citat:

Ursprungligen postat av Nerix (Inlägg 20445939)
Tror inte riktigt jag hänger med. Hur skulle en kompilator se att du använt fel metodnamn? Jag menar, du skriver ett test som gör det möjligt att te.x skriva och läsa ett namn-attribut i en user-klass. Skulle du stava fel här så finns det ingen kompilator som säger till.

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.

Nej du har inte insett vad en kompilator gör.

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.

Conny Westh 2012-07-31 05:47

Så här skulle motsvarande program se ut i C# med de metoder och properties jag var ute efter:

Kod:

using System;
using System.Collections.Generic;

namespace Test
{
        public class Person
        {
                private string _FirstName = "";
                public string FirstName
                {
                        get { return _FirstName; }
                        set { _FirstName = value; }
                }

                private string _LastName = "";
                public string LastName
                {
                        get { return _LastName; }
                        set { _LastName = value; }
                }

                public Person(string FirstName, string LastName)
                {
                        this.FirstName = FirstName;
                        this.LastName = LastName;
                }

                public override string ToString()
                {
                        return String.Format("{0} {1}",this.FirstName, this.LastName);
                }
        }
}

Kod:

using System;
using System.Collections.Generic;


namespace Test
{
        class PersonAge : Person
        {
                private int _BirthYear;

                public int BirthYear
                {
                        get { return _BirthYear; }
                        set { _BirthYear = value; }
                }

                public int Age
                {
                        get
                        {
                                return (2012 - BirthYear);
                        }
                }

                public PersonAge(string FirstName, string LastName, int BirthYear)
                        : base(FirstName, LastName)
                {
                        this.BirthYear = BirthYear;
                }

                public override string ToString()
                {
                        return String.Format("{0} ({1} år)", base.ToString(), this.Age);
                }
        }
}

Kod:

using System;
using System.Collections.Generic;


namespace Test
{
        class Program
        {
                static void Main(string[] args)
                {

                        List<Person> personer = new List<Person>();

                        personer.Add(new Person("Fredrik", "Framberg"));
                        personer.Add(new Person("Greta", "Gavelstam"));
                        personer.Add(new Person("Urban", "Urberg"));
                        personer.Add(new Person("Anna", "Ambtesteg"));

                        Console.WriteLine("Visa alla Person i personer...");
                        foreach (Person person in personer)
                        {
                                Console.WriteLine(person);
                        }

                        List<PersonAge> personAges = new List<PersonAge>();
                        personAges.Add(new PersonAge("Henrik", "Hammarberg", 1956));
                        personAges.Add(new PersonAge("Kristina", "Karlestam", 1983));
                        personAges.Add(new PersonAge("Hans", "Hallin", 1967));
                        personAges.Add(new PersonAge("Berit", "Bygdén", 1974));

                        Console.WriteLine();
                        Console.WriteLine("Visa alla PersonAge i personAges...");
                        foreach (PersonAge person in personAges)
                        {
                                Console.WriteLine(person);
                        }

                        Console.WriteLine();
                        Console.WriteLine("Kopiera alla PersonAge till personer...");
                        foreach (Person person in personAges)
                        {
                                personer.Add(person);
                        }

                        Console.WriteLine();
                        Console.WriteLine("Visa alla Person och PersonAge i personer...");
                        foreach (Person person in personer)
                        {
                                Console.WriteLine(person);
                        }

                        Console.ReadKey();
                }
        }
}

Kod:

Visa alla Person i personer...
Fredrik Framberg
Greta Gavelstam
Urban Urberg
Anna Ambtesteg

Visa alla PersonAge i personAges...
Henrik Hammarberg (56 år)
Kristina Karlestam (29 år)
Hans Hallin (45 år)
Berit Bygdén (38 år)

Kopiera alla PersonAge till personer...

Visa alla Person och PersonAge i personer...
Fredrik Framberg
Greta Gavelstam
Urban Urberg
Anna Ambtesteg
Henrik Hammarberg (56 år)
Kristina Karlestam (29 år)
Hans Hallin (45 år)
Berit Bygdén (38 år)


Conny Westh 2012-07-31 06:32

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:

#################################################################
# File: Makefile
# Author: Conny Westh, 2012
#################################################################
# This is a sample program in C#, works perfect in both Windows 7
# with Visual Studio 2010 and in ubuntu 12.04 with mono-mcs
# Command: sudo apt-get install mono-mcs
# to optain the C# compiler needed in ubuntu.
# This sample code demonstrates inheritance, property get and set
# override of method ToString(), Polymorphism, calculated read only
# property...
#################################################################
person : Program.cs Person.cs PersonAge.cs
        mcs -out:person Program.cs Person.cs PersonAge.cs
        @chmod 777 person

.PHONY : clean
clean :
        @rm -f person *.??~ Makefile~


Jake.Nu 2012-07-31 08:02

Citat:

Ursprungligen postat av ConnyWesth (Inlägg 20446074)
Du visar ju prov på att inte förstå programmeringens grunder över huvud taget, så dina kommentarer behöver ingen ens fundera på.

Om du inte begriper objektorienterad programmering så bör du inte komma med fullkomligt idiotiska inlägg här i forumet.

Jag gjorde mitt inlägg med en viss "twist" tror jag.. Var nog lite naiv som trodde att du skulle förstå vad jag menade, fast nu i efterhand inser jag att du inte kan förstå..
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.

Clarence 2012-07-31 09:48

Citat:

Ursprungligen postat av ConnyWesth (Inlägg 20446077)
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

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.

Du kanske inte insett det, men om du försöker använda en odeklarerad variabel för annat än tilldelning så får du en notis om det. Så om du gör en tilldelning till fel variabelnamn kommer du också få en notis om det när du försöker accessa den senare.

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