Obsah
Nette\Object
Nette\Object je společným předkem všech tříd Nette Frameworku.
V jiných programovacích jazycích takové třídy existují automaticky
(v Pascalu TObject, DOT.NET má System.Object a Java
nebo Ruby mají Object), ale v PHP nic takového neexistuje. Jde
o třídu dostatečně transparentní, neměla by způsobovat žádné kolize,
proto ji můžete jako základní třídu pro své třídy používat i vy.
class MyClass extends Nette\Object
{
}
Reflexe
Základní třída umožňuje snadný přístup k sebereflexi pomocí metody
getReflection() (vrací Nette\Reflection\ClassReflection):
$object = new MyClass();
$res = $object->getReflection()->hasMethod('test'); // má třída metodu test?
$className = $object->getReflection()->getName(); // zjistí jméno třídy
Náprava nekonzistentního generování chyb
PHP reaguje na přístup k nedeklarovaným členům značně nekonzistentně:
$obj->undeclared = 1; // projde bez hlášení
echo $obj->undeclared2; // generuje Notice
MyClass::$undeclared = 1; // generuje Fatal error
$obj->undeclared(); // generuje Fatal error
Většinou se přitom jedná o překlepy, které bývají zdrojem obtížně nalezitelných chyb.
Objekty tříd, které jsou potomky Nette\Object, vždy při
přístupu k nedeklarovanému členu vyhazují výjimku MemberAccessException.
Gettery a settery
Termínem property se
označují speciální členy
tříd, které umožňují pracovat s metodami tak, jako by to byly
proměnné. U Nette\Objectu se jedná o gettery a settery. Zvenku
vypadají jako obyčejná proměnná, ale přístup k ní máme plně pod
kontrolou. Můžeme tak validovat vstupy nebo generovat výstupy až
v případě potřeby.
- Getter i setter musí být veřejná metoda.
- Getter je povinný, setter volitelný (v tom případě pak získáme read-only proměnnou, write-only proměnné nejsou podporovány).
- Getter nepřijímá žádný parametr, setter právě jeden – novou hodnotu.
- Názvy jsou citlivé na velikost písmen (case-sensitive). První písmeno property může být malé i velké, mělo by to ale být anglické písmeno případně podtržítko.
class Circle extends Nette\Object
{
private $radius;
public function getRadius()
{
return $this->radius;
}
public function setRadius($radius)
{
// hodnotu před uložením validujeme
$this->radius = max(0, (float) $radius);
}
public function getArea()
{
return $this->radius * $this->radius * M_PI;
}
}
$circle = new Circle();
$circle->radius = 12; // volání $circle->setRadius(12);
echo 'Radius: ' . $circle->radius; //volání $circle->getRadius();
echo 'Area: ' . $circle->area; //volání $circle->getArea()
Kromě toho, přidáme-li kruhu property vyplněn/nevyplněn,
přirozenější než $circle->getFilled() je volání
$circle->isFilled(). I proto akceptuje Nette obě formy,
přičemž pokud existuje getFilled(), zavolá se ona – má
přednost.
class FillableCircle extends Circle
{
private $filled;
public function isFilled()
{
return $this->filled;
}
public function setFilled($filled)
{
//opět validace
$this->filled = (bool) $filled;
}
}
$circle = new FillableCircle();
$circle->filled = TRUE; //volání $circle->setFilled(TRUE);
echo 'Filled: ' . $circle->filled; //volání $circle->isFilled();
Jedná se jen o syntaktické pozlátko, jehož významem je pouhé zpřehlednění kódu. Pokud nechcete, tak properties nemusíte používat.
Vlastnosti se dají použít i pro zjednodušení výše uvedeného příkladu se sebereflexí:
$className = $object->reflection->name; //namísto $object->getReflection()->getName()
Události
Pokud potřebuji volat v nějakém okamžiku více funkcí se stejnými parametry, mohou se mi hodit události (events).
class Zahrada extends Nette\Object
{
//deklarace ve třídě
public $onSound;
}
function kocka($zvuk)
{
echo $zvuk === 'haf' ? 'lek' : '';
}
function pes($zvuk)
{
echo $zvuk === 'mňau' || $zvuk === 'haf' ? 'haf' : '';
}
$zahrada = new Zahrada;
// nastavím handlery
$zahrada->onSound[] = 'kocka';
$zahrada->onSound[] = 'pes';
$zahrada->onSound[] = function ($zvuk) { //handlerem může být i anonymní funkce
echo strlen($zvuk) > 2 ? 'haf' : 'lek';
};
$zahrada->onSound('haf'); // vypíše lekhafhaf
Rozšiřovací metody
Pokud chcete do nějaké třídy dopsat metodu a z nějakého důvodu to nemůžete realizovat poděděním, tak můžete použít extension method.
class MyClass extends Nette\Object
{
public $a;
public $b;
}
// deklarace budoucí metody MyClass::join()
function MyClass_join(MyClass $_this, $separator)
{
return $_this->a . $separator . $_this->b;
}
MyClass::extensionMethod('join', 'MyClass_join');
MyClass::extensionMethod('repeatB', function (MyClass $_this, $times) {
return str_repeat($_this->b, $times);
});
$obj = new MyClass();
echo $obj->join(' ');
echo $obj->repeatB(5);
Viz také:



