EN | CS | Přihlásit | Registrovat

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\Reflecti­on\ClassReflec­tion):

$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 MemberAccessEx­ception.

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é:


Login to submit a comment