Autor Zpráva
Camo
Profil
Dobrý večer všetkým,
tak ak dovolíte budem zase za blbého:
Môže mi prosím vás niekto vysvetliť túto vetu z manuálu?
Members declared as private may only be accessed by the class that defines the member."[/i]
Podľa mňa je tam napísané, že k členom označeným ako private môže pristupovať len trieda, ktorá tie členy definuje. To znie skoro ako keby k tým privat členom nemohli pristupovať potomkovia triedy.
Chápem to správne, že sa k tým privat členom v podstate nedá pristupovať prepísanými metódami? Nejak mi uniká podstata k čomu to je dobré. doteraz som všetko definoval ako privat, ale nikdy som ešte neprepisoval takže som na to nenarazil. Alebo je za tým ešte niečo iné? Tá definícia v php.net je úplne o ničom a aj iné čo som čítal radšej alibisticky používajú pri dedení public napr. http://interval.cz/clanky/oop-v-php-dedicnost/
Jednoduchý príklad:
<?php
class base{
      private $a = 33;

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

     public function getAll(){
        echo 'private $a - '.$this->a.'<br>';
        echo 'private function getA() - '.$this->getA();
     }

}

class child extends base{
     public function getAll2(){
        echo 'private $a - '.$this->a.'<br>';
        echo 'private function getA() - '.$this->getA();
     }
}

$o = new child();
echo $o->getAll();
echo $o->getAll2();  

?>
Prvé echo funguje a druhé echo vypíše:
Notice: Undefined property: child::$a in C:\Apache24\htdocs\DROM\DROM.php on line 31
private $a -

Fatal error: Call to private method base::getA() from context 'child' in C:\Apache24\htdocs\DROM\DROM.php on line 32
Tori
Profil
Camo:
Podľa mňa je tam napísané, že k členom označeným ako private môže pristupovať len trieda, ktorá tie členy definuje.
Správně, třída. Tj. kterákoli instance dané třídy má přístup i k soukromým proměnným jiných instancí téže třídy.
Jan Tvrdík
Profil
Camo:
To znie skoro ako keby k tým privat členom nemohli pristupovať potomkovia triedy.
Ano, přesně tak. Dál se mi to nechce číst :)
Camo
Profil
Tori:
"kterákoli instance dané třídy má přístup i k soukromým proměnným jiných instancí téže třídy."
Toto som nepochopil. Jediný spôsob ako môže mať jedna inštancia prístup k vlastnostiam inej inštancie je podľa mňa cez static... Môžeš to trochu rozviesť?
Jan Tvrdík:
Tak ako presne mám chápať zápis $o->getProtectedMembers( ktorý normálne funguje ) ak $o je potomkom nejakej triedy, ktorá definuje tie privat členy.
Tori
Profil
class A {
    private $x;
    public function __construct($x)
    {
        $this->x = $x;
    }
    
    public function test(A $other)
    {
        echo "<br>cizí proměnná x = ".$other->x;
    }
}

$instance1 = new A(1);
$instance2 = new A(2);
$instance3 = new A(3);

$instance1->test($instance2);  // vypíše "x = 2"
$instance1->test($instance3);  // vypíše "x = 3"

Jediný spôsob ako môže mať jedna inštancia prístup k vlastnostiam inej inštancie je podľa mňa cez static
To nejsou vlastnosti instancí, ale vlastnosti třídy (které vypadají jako společné pro všechny instance, ale jsou přístupné i bez instancí).

edit: V tom manuálu je ukázané totéž.
Camo
Profil
Tori:
No dobre vidím, že je to možné. Len mi nejde do hlavy načo je to dobré. Podľa mňa je prehľadnejšie pristupovať cez nejaký geter ku tým vlastnostiam iných objektov.
A ako by sa dalo pristúpiť k privat členovi ak by som potreboval prepísať nejakú metódu? Cez parent::$var mi to nejde...
Jan Tvrdík
Profil
Tori:
Mám takový dojem, že se mu snažíš vysvětlit pokročilé chování private a on nechápu pořádně ani to úplně základní :)

Camo:
Možná by nebylo od věci přečíst si další díl toho seriálu na intervalu – interval.cz/clanky/oop-v-php-viditelnost
Camo
Profil
Jan Tvrdík:
Stačila by mi len tá odpoveď na moju predošlú otázku pre vás:
Tak ako presne mám chápať zápis $o->getProtectedMembers( ktorý normálne funguje ) ak $o je potomkom nejakej triedy, ktorá definuje tie privat členy ak vy píšete, že potomkovia nemajú prístup?
Tori
Profil
Camo:
ako presne mám chápať zápis $o->getProtectedMembers
O jaké $o->getProtectedMembers() mluvíte?
Camo
Profil
Tori:
Má tam byť privat miesto protected....
Proste potrebujem nejaké vysvetlenie tých dvoch vecí, trebárs odkaz kde je to rozobraté(môže byť Aj). Aký je v tom v praxi rozdiel???

Ten príklad som myslel ako
$o - potomok triedy T ktorá ma nejakú private metódu getPrivateT().
V definícii je napísané, že potomkovia nemajú prístup k private členom.
Ako je teda možné, že mi funguje zápis
$o->getPrivateT() ???
Joker
Profil
Camo:
Ako je teda možné, že mi funguje zápis
Protože to nejspíš je metoda té samotné třídy a ona k nim pochopitelně přístup má.
Takovým způsobem se dá k private atributu dostat odkudkoliv.

class A {
    private $foo;
    
    public function setFoo($val) {
      $this->foo = $val;
    }
    
    public function getFoo() {
      return $this->foo;
    }
}
Atribut foo je sice nominálně private, ale přes metody getFoo a setFoo se k němu dá efektivně dostat odkudkoliv.
Camo
Profil
Blbosti trepem... $o->getPrivateT() naozaj nefunguje. Niečo sa mi asi prisnilo...

Ale ešte jednu vec mám ak dovolíte.
Nemal by mať potomok prístup k private členovi rodiča cez parent::$privMember??? Mne to teda nefunguje, ale zaujíma ma kedy sa má/nemá tento zápis použiť?
juriad
Profil
Camo:
https://gist.github.com/juriad/5676350
Pokud ti není jasné, proč některá odkomentovaná řádka funguje a má takový výsledek nebo proč nefunguje nějaká zakomentovaná, ptej se. (Snad jsem tam neudělal nějakou chybu)

K tvé otázce: NE. K privátní proměnné se dostane jen instance té třídy a nejde to obejít pomocí parent::.
Camo
Profil
juriad:
Díky za námahu. Prešiel som si to celé a myslím, že už chápem. Na začiatku som myslel, že protected je striktnejšie ako private.
Sa mi zdá, že sa častejšie stretávam s private definíciou, čo ale podľa mňa moc nenapomáha dedičnosti. Či sa mýlim?
juriad
Profil
Pokud použiješ private proměnnou, tak říkáš, že tato proměnná má smysl jen při této implementaci. Podobně s private metodou.
Modifikátory u proměnných často bývají striktnější, protože u proměnné nemůžeš povolit čtení a zakázat zápis.
Navíc během implementace často víš, že tento kus by šel udělat optimálněji a tak si rovnou připravíš protected metodu (takové body k rozšíření), která zatím bude provádět jen to základní.

<?php

# dynamické pole, do kterého lze jen přidávat na konec
class Pole {
  private $delka;
  private $pole;
  private $prvku;
  
  function __construct($pocatecniDelka = 4) {
    $this->pole = $this->vytvorPole($pocatecniDelka);
    $this->delka = $pocatecniDelka;
    $this->prvku = 0;
  }
  
  public function prvku() {
    return $this->prvku;
  }
  
  public function pridej($prvek) {
    if($this->prvku == $this->delka) {
      $novaDelka = $this->getNovaDelka($this->delka);
      $pole2 = $this->vytvorPole($novaDelka);
      for($i = 0; $i < $this->delka; $i++) {
        $pole2[$i] = $this->pole[$i];
      }
      $this->pole = $pole2;
      $this->delka = $novaDelka;
    }
    $this->pole[$this->prvku++] = $prvek;
  }
  
  protected function getNovaDelka($staraDelka) {
    return $staraDelka+1;
  }
  
  public function vrat($index) {
    return $this->pole[$index];
  }
  
  private function vytvorPole($novaDelka) {
    return array_fill(0, $novaDelka, 0);
  }
}

# to same pole s amortizovane lepsi slozitosti
class LepsiPole extends Pole {
  protected function getNovaDelka($staraDelka) {
    return $staraDelka*2;
  }
}

$p = new Pole(); # zmen na LepsiPole a pozoruj zmenu v delce testu
for($i = 0; $i < 10000; $i++) {
  $p->pridej($i);
}

for($i = 0; $i < 10000; $i++) {
  if($p->vrat($i) != $i) { # pokud by nahodou prvek neodpovidal tomu, ktery byl vlozeny:
    echo $i, ": ", $p->vrat($i), "\n";
  }
}
Camo
Profil
juriad:
Dobre myslím, že chápem...

Ale zase ak pridám do potomka nový parameter a chcem ho nastaviť v konštruktore, tak musím najprv volať
parent::__construct( params ) aby to fungovalo. Je to tak? ak teda pôvodný konštruktor nastavuje nejaké private premenné, alebo volá private metódy.
juriad
Profil
Camo:
To, že nevypíše nic je v pořádku: nedošlo k žádné chybě, všechny prvky mají správnou hodnotu.

http://php.net/manual/en/language.oop5.decon.php
Note: Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required. If the child does not define a constructor then it may be inherited from the parent class just like a normal class method (if it was not declared as private).


Ano, v takovém případě musíš zavolat parent::__construct, v opačném případě budou proměnné neinicializované a kód se ti nejspíš sesype.
Camo
Profil
juriad:
Tak to by bolo všetko.
Ďakujem za vysvetlenie.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: