PHP protected property – co mi uniká?

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

Zdravím, toto není uplně nette, ale obecně PHP. Je toto správné chování přístupu k protected property? Pokud 2 třídy dědí jednu nadžezenou a přepošlu si potomka z jedné do druhé, jaktože můžu přistoupit k její protected property? Možná už sem jenom přepracovanej :) Potřeboval bych aby to možné nebylo, poradíte? Díky

class a
{
protected $aa = 1;
}

class b extends a
{
function foo()
{
$c = new c;

$c->foo($this);
}
}

class c extends a
{
function foo(b $b)
{
print_r($b->aa);
 }
}

$b = new b;

$b->foo();

Šaman
Člen | 2666
+
0
-

Cožeco? Trochu se v tom ztrácím, protože to není naformátované, ale dva potomci o sobě nic nevědí. Ledaže by dostali instanci toho druhého, ale pak maji přístup jen k public.
Protected znamená, že potomek má přístup k property předka (může s ní pracovat).
A private znamená, že ani potomek nesmí sahat na property definovanou v předkovi.


Edit: pokus o přeformátování

<?php
class a
{
	protected $aa = 1;
}

class b extends a
{
	function foo()
	{
		$c = new c;
		$c->foo($this);
	}
}

class c extends a
{
	function foo(b $b)
	{
		print_r($b->aa);
	}
}

$b = new b;
$b->foo();
?>

Tak ne, ten print_r nebude fungovat. Potomek má přístup do property předka (tedy $this->aa) ale $b je cizí třída, tam vidí jen public.

Edit: viz dále

Editoval Šaman (5. 4. 2016 23:55)

David Matějka
Moderator | 6445
+
+1
-

@Šaman nemas pravdu :) https://3v4l.org/jI01O

@j.salak ano, je to tak. viz http://php.net/…sibility.php#… … modifikatory viditelnosti nemaji vliv na jen objekt, ale na celou tridu

CZechBoY
Člen | 3608
+
0
-

Moc dobře nechápu o co se snažíš. Pokud dědíš tu třídu A tak všechny protected budou vidět ve všech potomcích, private uvidí jen třída A.
Pokud potřebuješ property viditelnou pouze v B tak použij private – ale nebude zase vidět v A.

Zkus se trošku prohrabat tím manuálem viditelnosti co poslal David M.

Šaman
Člen | 2666
+
+1
-

Uff, co to je za podivnou medicínu? Ono to trochu vážně funguje.
Ale ne zas tak moc, abych se na to chtěl spoléhat. (Tenhle druhý výsledek jsem ale očekával už od začátku. Člověk se furt učí… :)

V každém případě sorry za dezinformaci.

Editoval Šaman (5. 4. 2016 23:48)

Oli
Člen | 1215
+
0
-

@Šaman, @DavidMatějka jestli mě něco neuniká, tak máte pravdu oba. Tenhle příklad funguje protože, pokud neuvedeš modifikátor viditelnosti, tak se metoda považuje za public. Protected metodu foo třída B skutečně nevidí…

EDIT:// Nic, až teď jsem si všiml, že se bavíme o property a ne o metodě… Jdu spát :-)

Editoval Oli (5. 4. 2016 23:39)

ViPEr*CZ*
Člen | 818
+
+1
-

To je magie. @Šaman osobně se mi to taky moc nelíbí. Dokonce to je tak black, že to sežere i v třídě c a metodě foo() záměnu aa za bb a vytvoří se nová public proměnná :-/

Editoval ViPEr*CZ* (6. 4. 2016 8:32)

j.salak
Člen | 42
+
0
-

Takže to všem funguje, super :) každopádně potřebuju poradit jak udělat aby to nefungovalo, tzn. aby pořád byla tam $aa property zvenku nedostupná, protože na to mám navázané nějaké gettery a takhle mi je to nezavolá a vrací mí přímo obsah té property a to je pro mě nežádoucí.

Zkoušel jsem to volat i přes call_user_func() ale nepomohlo.

Zatím jediné čím to vypadá, že bych to mohl napravit, je opětovným nadefinováním protected $aa; v třídě „b“. Pak už se to chová přepokládaně, ale není to hezké.

Editoval j.salak (6. 4. 2016 10:16)

David Matějka
Moderator | 6445
+
0
-

každopádně potřebuju poradit jak udělat aby to nefungovalo, tzn. aby pořád byla tam $aa property zvenku nedostupná, protože na to mám navázané nějaké gettery

snadno to udelat nepujde :) pokud bys tu promennou aa potreboval jen v „a“ a ne v „b“ a „c“, tak ji muzes udelat private. A nemuzes ty gettery (jestli tim myslis metody) volat primo?

j.salak
Člen | 42
+
0
-

David Matějka napsal(a):

každopádně potřebuju poradit jak udělat aby to nefungovalo, tzn. aby pořád byla tam $aa property zvenku nedostupná, protože na to mám navázané nějaké gettery

snadno to udelat nepujde :) pokud bys tu promennou aa potreboval jen v „a“ a ne v „b“ a „c“, tak ji muzes udelat private. A nemuzes ty gettery (jestli tim myslis metody) volat primo?

Jojo, já předělám ten koncept, to neni problém, jen jsem myslel jestli není nějaká jednoduchá cesta jak to obejít abych do toho hotovýho nemusel šahat :) ale v pohodě, jen si na to musim dát do budoucna pozor. Díky za rady.

j.salak
Člen | 42
+
0
-

j.salak napsal(a):

David Matějka napsal(a):

každopádně potřebuju poradit jak udělat aby to nefungovalo, tzn. aby pořád byla tam $aa property zvenku nedostupná, protože na to mám navázané nějaké gettery

snadno to udelat nepujde :) pokud bys tu promennou aa potreboval jen v „a“ a ne v „b“ a „c“, tak ji muzes udelat private. A nemuzes ty gettery (jestli tim myslis metody) volat primo?

Jojo, já předělám ten koncept, to neni problém, jen jsem myslel jestli není nějaká jednoduchá cesta jak to obejít abych do toho hotovýho nemusel šahat :) ale v pohodě, jen si na to musim dát do budoucna pozor. Díky za rady.

Tak ono to tak jednoduchý nebude, protože i když bych to zjednodušil

<?php

class a
{
	protected $aa = 1;
}

class b extends a
{
	function foo()
	{
		$c = new c;

		print_r($c->aa);
	}
}

class c extends a
{

}

$b = new b;

$b->foo();

?>

tak stejně pořád můžu k tý protected property,l tak hold musim volat ty gettery (metody) přímo.

Šaman
Člen | 2666
+
+4
-

To volání getterů přímo se mi osvědčilo skoro vždy. Výjimka je v presenteru $this->template, veškerá volání v šablonách a v ORM entitách magické property (které jsou ale vždy zapsané v anotacích).

Když jsem to zkoušel používat častěji, tak to vedlo k nekonzistenci v kódu, sám jsem nevěděl, jestli volám metodu, nebo pravou property a po nějaké době jsem si začal myslet, že ta property opravdu existuje. Teď už i ostatní metody v presenteru raději volám getterem ($presenter->getUser()).