Rozšiřující metody pro rozhraní (extensionMethod)

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Tomáš Kuba
Člen | 15
+
0
-

Prosím nakopněte mě někdo jak použít Rozšiřujíci metody společně s rozhraním? Dokumentace je na toto téma torchu skoupá

Napsal jsem si toto, ale je to samozřejmě nesmysl:

// PHP 5.2
interface INestedSet {

}

INestedSet::extensionMethod('test',  callback('test'));

function test () {
    return "I am test";
}

class myClass extends Object implements INestedSet {
	//…
}

$obj = new myClass;
echo $obj->test;

Editoval Tomáš Kuba (16. 9. 2011 11:23)

norbe
Backer | 405
+
0
-

Mohl by Ti pomoci příspěvěk od Davida.

Jestli jsem správně pochopil princip, tak by to mělo pro tvůj příklad fungovat následovně:

interface INestedSet {
	function test();
}

// přidá do všech tříd (dědících od Nette\Object) implementujících INestedSet rozhraní metodu test
Nette\Object::extensionMethod('INestedSet::test',  callback('nejaka_funkce'));
Tomáš Kuba
Člen | 15
+
0
-

Norbe, díky za bleskové nakopnutí – řešení je takto:

// PHP 5.2
interface INestedSet {
	//zde opravdu nic být nemusí
}

function test() {
	return "I am test";
}

Object::extensionMethod('INestedSet::test', callback('test'));

class myClass extends Object implements INestedSet {
	//…další metody
}

$obj = new myClass;
echo $obj->test();

Editoval Tomáš Kuba (16. 9. 2011 12:11)

norbe
Backer | 405
+
0
-

To že tam nic být nemusí neznamená že by to tam být nemělo ;)

Tomáš Kuba
Člen | 15
+
0
-

Pokud tam tu deklaraci metody test napíši tak jí PHP samozřejmě vyžaduje v myClass také imlementovat. To není v tento moment žádoucí. Naopak interface je v příkladu zneužit jako nástroj pro přidání tzv. behaviors – čili chování.

Dovedu si však představit, že interface bude deklarovat metodu např. getDatabaseConnection() nebo getTableName(), které budou muset být implementovány proto, aby „NestedSet chování“ vědělo jak a kam se napojit.

norbe
Backer | 405
+
0
-

Aha, to mi nějak nedošlo. Poradil bych ti, aby jsi alespoň přidal anotace @method, aby bylo IDE schopno napovídat, ale zjistil jsem, že to netbeans u interfaců nepodporuje…

Filip Procházka
Moderator | 4668
+
0
-

Nebyly by lepší nějaké abstraktní třídy?

Tomáš Kuba
Člen | 15
+
0
-

Rád si nechám poradit. Klasická dědičnost mi přišla neohrabaná (to není z mé hlavy samozřejmě – na takové napady přicházejí větší mozky než já :) To že je Model obohacen o vlastnosti/chování NestedSetu (getParentNode, addBeforeNode apod.) mi prijde jako hezký přístup. Modelu pak stačí napsat …implements INestedSet a mám k dispozici vše co potřebuju pro traverzování kolem stromu.

HosipLan, můžeš malinko rozvést návrh s abstract třídami prosím?

Tomáš Kuba
Člen | 15
+
0
-

Pro doplnění: Pokud implementujete uvedený přístup rozšířeného rozhranní tak metodě test jsou předány všechny public paramtery myClass. Ostatně tak jak je psáno v dokumentaci :)

…tak ještě lépe (opět smekám před Davidem Grudlem a spoluautory Nette) funkce test dostane jako argument samozřejmě referenci na instanci celého objektu = v tomto případě tedy myClass:

// PHP 5.2
interface INestedSet {
        //zde opravdu nic být nemusí
}

function test($that) {
        return "I am test function of " . $that->getReflection()->getName();
}

Object::extensionMethod('INestedSet::test', callback('test'));

class myClass extends Object implements INestedSet {
        //…další metody
}

$obj = new myClass;
echo $obj->test();

Editoval Tomáš Kuba (16. 9. 2011 15:07)

Filip Procházka
Moderator | 4668
+
0
-

Co takto?

abstract class NestedSet extends Nette\Object
{
	abstract public function test();
}

class myClass extends NestedSet
{
}

$node = new myClass();
$node->test();

Čtení na dobrou noc:

http://martinfowler.com/…ritance.html
http://martinfowler.com/…ritance.html
http://martinfowler.com/…ritance.html