Objektum-Orientált fejlesztés
PHP(5) nyelven


Simon Bence
2009-09-17
Mi az az
objektum-orientáltság?
Programozási paradigma

         +
     Absztrakció
“
Egymással kommunikáló objektumok
rendszere
Objektum?
Adat és a rajta értelmezett művelet
Elemi entitás

                    &
           Való világ modellezése

                    &
Absztrakt fogalmak megjelenése a programban
?
Például: “téglalap”
(Adat)
A téglalapnak van...




    ...“a” oldala
    ...”b” oldala
(Művelet)
A téglalap tud...




... teruletSzamitas()
... keruletSzamitas()
Téglalap

                 Téglalap          Téglalap
Téglalap
                      Téglalap

           Téglalap                    Téglalap



                                 Téglalap
    Téglalap
Téglalap

                 Téglalap          Téglalap
Téglalap
                      Téglalap

           Téglalap                    Téglalap



                                 Téglalap
    Téglalap

       {         Osztály
Osztály?
Az objektumok viselkedését definiáló leírás
Jó-e ez nekem?
Igen!
 De miért is?
Miért?
  - Karbantarthatóság
  - Bővithetőség
  - Újrafelhasználhatóság
  - Fejlesztési idő csökkentése
Karbantarthatóság

- a kódoknak egyszer kell szerepelniük
- minden kódnak jól meghatározható hely
- lehetőség egységtesztekre
+ a kommentek fontosak
Bővíthetőség



- leszármaztatás
Újrafelhasználhatóság


- kohézív osztályok
- felületre tervezés (hordozhatóság)
Nem velejárója, lehetősége!
Az objektumkezelés költsége
class A
{
          public function test($a)
          {
                   $a += 1;
          }
}

function test($a)
{
        $a += 1;
}

$array = array();
$time = microtime(true);
for ($i = 0; $i < 50; $i++)
{
    $array[$i] = new A();
}
echo microtime(true) - $time, '<br/>'; // 0.00006s

$a = new A();
$time = microtime(true);
for ($i = 0; $i < 500; $i++) {
    $a->test(1);
}
echo microtime(true) - $time, '<br/>'; // 0.00047s

$time = microtime(true);
for ($i = 0; $i < 500; $i++) {
    test(1);
}
echo microtime(true) - $time, '<br/>'; // 0.00043s
Az
objektumok és osztályok
$circle = new Circle();
$circle1 = new Circle();
$circle2 = new Circle();
$circle3 = new Circle();
           ...
“
Az objektum egy valós, vagy absztrakt,
azonosítható, egyedi entitás, amely a vizsgált
környezet egy jól definiált szereplője
“
Az adat és a rajta értelmezett művelet együttese
“
Az objektum egy rendszer egyedileg
azonosítható szereplője, amelyet a külvilág felé
mutatott viselkedésével, belső struktúrájával és
állapotával jellemezhetünk
Gyártsunk objektumot!
     (A konstruktor)
Konstruktor:
  - Objektumszintű metódus
  - Inicializáló blokk
  - Lehetnek paraméterei
  - Csak egy lehet belőle
  - Általában publikus
Például...
class Rectangle
{
        protected $a;
        protected $b;

       public function __construct()
       {
               $this->a = 3;
               $this->b = 5;
       }
}

$t = new Rectangle();
Vagy...
class Rectangle
{
        protected $a;
        protected $b;

       public function __construct($a, $b)
       {
               $this->a = $a;
               $this->b = $b;
       }
}

$t = new Rectangle(3, 5);
<< Osztály >>
“
Az osztály tehát egy sablon, ami az adott
fogalom tulajdonságait (attribútum) és a neki
küldhető üzeneteket (metódusok) írja le, mint
egy model
$attribútumok
Az osztályban meghatározott tulajdonságok
{   Bármilyen PHP változótípus lehet
           Akár másik osztály is       }
{
    $foo;
    $bar = 5;
    $something = “interesting text”;
    $array = array();
    $anOtherArray = array(‘a’, ’b’, ’c’);
    $object = new Object();
állapot
Az attribútumok összessége, jellemzi az objektumot
“
Az objektum állapotát az objektum
attribútumai által felvett értékek
összessége írja le
Pl.:
Triangle:
 $a = 7
 $b = 6
 $c = 5
public function metódusok() { /.../ }
“
Az objektum metódusokon keresztül
kommunikál a külvilággal és ezek
változtathatják meg az állapotát
class Triangle
{
         protected $a;
         protected $b;
         protected $c;

       public function getA()
       {
               return $this->a;
       }

       public function setA($a)
       {
               $this->a = $a;
       }
}

$t = new Triangle();
$t->setA(9);
echo $t->getA();
Az objektumok törlése
Az objektumok törlése
   Garbage collector
Nem lehetünk biztosak benne :(
     Elvben: alapvetöen, amint tud, töröl
__destruct()
Objektum törlésekor
register_shutdown_function()
          Script végén
register_shutdown_function()
Hibalehetöség! Vigyázzunk! (Pl. adatbázis kapcsolat lezárása)
Coupling
$a = new A(1, 2, 3);
$b = new B(4, 5);

... és A kódjában:

public function foo($b)
{
         $b->var = $this->var;
}
$a = new A(1, 2, 3);
$b = new B(4, 5);

... és A kódjában:

public function foo($b)
{
         $b->setVar($this->var);
}
Tervezési cél:
A kötések csökkentése, az egyes objektumok csak annyit tudjanak egymásról, amennyit szükséges
                                    (API-ra tervezés)
IS A   /   HAS A
HAS A 1: Gyenge tartalmazás (aggregáció)
       rész-egész kapcsolat, a részek alkotják az egészet
HAS A 2: Erős tartalmazás (kompozíció)
 a rész szorosan tartozik az egészhez, a részek nem élik túl az egészet
Cohesion
class SomethingWrong
{
        public function makeSandwich() { /.../ }
        public function countApples() { /.../ }
        public function deleteOldEntries() { /.../ }
        public function someOtherSillyThing() { /.../ }
}
Tervezési cél:
A kohézió növelése, az objektumok “jól-fókuszáltsága”
Az objektum-orientáltság
alapelvei és eszközei
Egységbe zárás
(Encapsulation)
Hm?
  -OOP alapelv
  - Adattagok és metódusok osztályba foglalása
  - Állapot és viselkedés együtt
Adatrejtés
(Data hiding)
Egységbe zárás   Adatrejtés
Láthatósági szintek
Hozzáférési kategóriákkal szabályozhatjuk
Public
Olyan attribútumok és metódusok, melyek korlátozás nélkül láthatóak a külvilág felé
Protected
Olyan attribútumok és metódusok, melyekhez a külvilág nem fér hozzá, de
leszármazott osztályok hozzáférnek
Private
Olyan attribútumok és metódusok, melyekhez a külvilág nem fér hozzá. A
leszármazott osztályok se látják!
A hozzáférést a tag elé írt módosítóval jelezzük...
                  public function foo($b)
                  {
                           /.../
                  }


                     ... vagy ...


                  protected $variable;
Adattagokhoz kívülről csak metódussal lehessen hozzáférni!
Alapértelmezetten a láthatóság public
Öröklődés
(Inheritence)
Az osztályok hierarchiába szervezése, öröklési lánc segítségével
Specializálás
(A láncon lefele tekintve specializáció (és kiegészülés), felfele nézve általánosítás)
class Shape { /.../ }
class Shape { /.../ }

class Circle extends Shape { /.../ }
class Shape { /.../ }

                                    class Circle extends Shape { /.../ }


class Triangle extends Shape { /.../ }                               class Rectangle extends Shape { /.../ }
“
A leszármazott osztály megkapja az ős
összes attribútumát és metódusát
class Fruit
{
        public function eat()
        {
                 echo “nyami”;
        }
}

class Orange extends Fruit
{
}

$orange = new Orange();
$orange->eat();

// Eredmény: nyami
Dinamikus kötés
class A
{
          protected $text = ‘Hello!’;

          public function sayHello()
          {
                   echo $this->text;
          }
}

class B extends A
{
        protected $text = ‘Namaste!’;
}

$b = new B();
$b->sayHello();


            Namaste!
Óvatosan a hierarchia kialakításával!
 (http://www.snopes.com/humor/nonsense/kangaroo.asp)
StdClass
{
    /.../
}
Többszörös öröklődés
Többszörös öröklődés
      Nincs!
Többszintű öröklődés
class Shape { /.../ }

                                    class Circle extends Shape { /.../ }


class Triangle extends Shape { /.../ }                               class Rectangle extends Shape { /.../ }



                                                                    class Square extends Rectangle { /.../ }
Metódus felülírás
(Method override)
class Fruit
{
        public function eat()
        {
                 echo 'nyam-nyam';
        }
}

class Apple extends Fruit
{
        public function eat()
        {
                 echo 'nyum-nyum';
        }
}
parent::
class Fruit
{
        public function eat()
        {
                 echo 'nyam-nyam';
        }
}

class Apple extends Fruit
{
        public function eat()
        {
                 echo 'nyum-nyum';
                 parent::eat();
        }
}

// Eredmény: nyam-nyamnyum-nyum
Absztrakt osztályok
  (Abstract classes)
Általánosítástetején van)
(Jól látszik abból, hogy az öröklési fa
Metódus >> Osztály
Szabályok
  - Metódus: nincs törzse
  - Osztály: nem példányosítható
Leszármazottjai is absztraktnak minősülnek, amíg nem
        implementálják az összes metódust
abstract class A
{
       abstract function foo();
}

$a = new A();

        HIBA!
Többalakúság
(Polimorphism)
IS A
Rectangle   IS A   Shape
“
Egy objektum nem csak saját osztályának, de
összes ős osztályának és interface példányának
is tekinthető
public function paintThis(Shape $s)
{
         /.../
}

$shape = new Shape();

...->paintThis($shape)
public function paintThis(Shape $s)
{
         /.../
}

$rectangle = new Rectangle();

...->paintThis($rectangle)
Interface-ek is!
Type hint
public function foo(someClass $var) { /.../ }
Metódus túlterhelés
  (Method overload)
Azonos nevű, de más szignatúrájú metódusok
Nincs!
Ilyen nincs!

class Pear
{
        public function foo()
        {
                 /* ... */
        }

       public function foo($var)
       {
                /* ... */
       }

       /* more code */
}
De még csak ilyen se!

  class Pear
  {
          public function foo()
          {
                   /* ... */
          }

         protected function foo($var)
         {
                 /* ... */
         }

         /* more code */
  }
Sőt, ilyen sem!

class Pear
{
        public function foo()
        {
                 /* ... */
        }

       public static function foo($var)
       {
                /* ... */
       }

       /* more code */
}
Megkerülhető:
 func_get_args()
Statikus módosító
  (Static modifier)
Attribútum & Metódus
self::
class Apple
{
        protected static $number = 0;

       public function __construct()
       {
                self::$number = self::$number + 1;
       }

       public static function getNumberOfApples()
       {
                return self::$number;
       }
}

$a = new Apple();
echo Apple::getNumberOfApples();
Late static binding
class A
{
          protected static $text = ‘Hello!’;

          public static function sayHello()
          {
                   echo self::$text;
          }
}

class B extends A
{
        protected static $text = ‘Namaste!’;
}

B::sayHello();
Hello!
 PHP 5.3-ig
Statikus tag   SOHA nem ér el objektumszintű tagot
class Apple
{
        protected $color = ‘red’;

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

       public static function getColor()
       {
                return $this->color;
       }
}

$a = new Apple(‘green’);
Apple::getColor();

               HIBA
Interface-ek
 (Interface)
“
Üzenetküldési szabályok definiálása
interface Drinkable
{
        public function drink();
}
Csak publikus metódus definiálható!
implements
class Beer implements Drinkable
{
        public function drink()
        {
                 //something good
        }
}
Implementálás szabályai
    -Több interface-t is implementálhat
    - Minden metódusát meg kell valósítsa
    - A megvalósítás szignatúrájának egyezni kell
Final módosító
(Final modifier)
Kőbe vésett!
Osztály & metódus
Abstract & Final
Óvatosan!
Műveletek
objektumokkal
if (   Objektum összehasonlítása   ){
[ Egymással ]
Állapotok összehasonlítás

        $a == $b
Pointer összehasonlítás

      $a === $b
[ Osztályokkal   (és interface-ekkel)   ]
is_a & instanceof
get_class, get_parent_class, is_subclass_of
Objektumok másolása
Objektumok másolása
           másolása
Objektumok
Klónozás
$copyOfObject = clone $object
shallow copy
Az attribútum objektum-mutatója másolódik le: ugyanarra az objektumra mutat,
                              mint az eredeti
                                 default
deep copy
Az attribútum objektum állapota másolódik le. Másik, innentől független objektum
& másik pointer létrehozása
$a = new Foo();
$a->setValue(3);
$a = new Foo();
$a->setValue(3);

$b = $a;
$b->getValue()
// Az eredmény: 3
$a = new Foo();
$a->setValue(3);

$b = $a;
$b->getValue()
// Az eredmény: 3

$b->setValue(5);
$a->getValue()
// Az eredmény: 5
Objektum iteráció
      (PHP5)
class Example
{
        public $var1 = 1;
        public $var2 = 2;
        public $var3 = 3;
        protected $var4 = 4;
        protected $var5 = 5;

       public function iterateAttributes()
       {
               foreach ($this as $key => $value)
               {
                      echo $key.’: ‘.$value.PHP_EOL;
               }
       }
}
$e = new Example();
$e->iterateAttributes();
   // Eredmény: 1, 2, 3, 4, 5
foreach ($e as $key => $value)
{
     echo $key.’: ‘.$value.PHP_EOL;
}
       // Eredmény: 1, 2, 3
Óvatosan!
 (Láthatóság)
Mágikus
metódusok
Speciális segítő függvények
__névtér()
publikus
__construct
__destruct
  __clone
__toString()
echo, print, printf...
  class Foo
  {
          $varA = 42;
          $varB = 'life';

          public function __toString()
          {
                   return $varA.', '.$varB;
          }
  }

  $a = new Foo();
  echo $a;
__call()
class Example
{
        public function __call($method, $argument)
        {
                 echo $method;
        }
}

$object = new Example();
$object->foo();

// eredmény: ‘foo’
__callStatic()
    PHP 5.3!
__set() & __get()
class Container
{
        protected $data = array();

       public function __get($name)
       {
                return $this->data[$name];
       }

       public function __set($name, $value)
       {
                $this->data[$name] = $value;
       }
}

$a = new Container();
$a->something = 20;
echo $a->something;
__isset() & __unset()
class Container2 extends Container
{
        public function __isset($name)
        {
                 return isset($this->data[$name]);
        }

       public function __unset($name)
       {
                unset($this->data[$name]);
       }
}

$a = new Container();
isset($a->name);
unset($a->name);
__sleep() & _wakeup()
__set_state()
  __toString()
var_export...
+1
__invoke()
  PHP 5.3!
Egyéb
lehetőségek
{   Kivételkezelés
                     }
throw new Exception(“This is gonna be bad”);
include
__autoload()
function __autoload($className)
{
   require_once $DOCUMENT_ROOT.“classes/class.”.$className.“.php”;
}
           & regisztrálás az spl_autoload_register függvénnyel
Hova
tovább?
Lehetőségek...

- UML
- Tervezési minták
- Objektumorientált adatmodell
- Fejlesztési módszertanok
- Reflection api
Lehetőségek...

- UML
- Tervezési minták
- Objektumorientált adatmodell
- Fejlesztési módszertanok
- Reflection api
Lehetőségek...

- UML
- Tervezési minták
- Objektumorientált adatmodell
- Fejlesztési módszertanok
- Reflection api
Lehetőségek...

- UML
- Tervezési minták
- Objektumorientált adatmodell
- Fejlesztési módszertanok
- Reflection api
Lehetőségek...

- UML
- Tervezési minták
- Objektumorientált adatmodell
- Fejlesztési módszertanok
- Reflection api
getConstants      getDocComment
  isProtected
                          getName                 hasMethod
             isAbstract              isOptional
                                                              isInterface
                   getStartLine
                                  isUserDefinied
getModifierNames
                    getDefaultValue
        getParentClass                            returnsReference
                          export
                                         getFileName     invoke
       getMethod
                              setAccessible
Köszönöm!
Kérdések?
http://download.perfectmess.hu/oop.ppt

Objektum Orientalt Fejlesztes PHP5-ben