Obiekty PHP a tablice - porównanie wydajności podczas iteracji

91

Mam ogromną liczbę obiektów PHP dla sieci neuronowej, dla których muszę iterować i wykonać na nich obliczenia. Zastanawiałem się, czy lepiej byłoby używać tablicy asocjacyjnej zamiast instancji klas?

Mam do czynienia z 3640obiektami i iteracją 500czasu (w najlepszym przypadku), więc każda mikro-optymalizacja bardzo pomaga. Czy byłoby to nieuchronnie szybsze $object['value']niż to $object->value?

Edycja: Więc oba są takie same. Ale myślę, że konstruktor miałby trochę narzutów? Tak czy inaczej, nie sądzę, żebym chciał zamienić moje piękne zajęcia na brudne tablice: P

Louis
źródło

Odpowiedzi:

65

Opierając się na kodzie Quazzle, uruchomiłem następny kod (5.4.16 Windows 64 bity):

<?php
class SomeClass {
    public $aaa;
    public $bbb;
    public $ccc;
    }

function p($i) {
  echo '<pre>';
  print_r($i);
  echo '</pre>';
}


$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage(); 
for ($i=0; $i<1000; $i++) {
    $z = array();
    for ($j=0; $j<1000; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];            
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);

$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage(); 
for ($i=0; $i<1000; $i++) {
    $z = new SomeClass();
    for ($j=0; $j<1000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);

$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage(); 
for ($i=0; $i<1000; $i++) {
    $z = new stdClass();
    for ($j=0; $j<1000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);  
?>

I uzyskałem następny wynik:

arrays: 1.8451430797577

memory: 460416

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 1.8294548988342

memory: 275696

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 2.2577090263367

memory: 483648

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

Wniosek dla php 5.4

  1. Klasa jest szybsza niż Arrays (ale marginalnie).
  2. stdClass jest zła.
  3. Klasa zużywa mniej pamięci niż Arrays. (około 30-40% mniej !!)

ps: uwaga, jeśli klasa jest zdefiniowana, ale członkowie to członkowie, użycie tej klasy jest wolniejsze. Zużywa też więcej pamięci. Najwyraźniej sekret polega na zdefiniowaniu członków

Aktualizacja

Zaktualizowałem z php 5.4 do php 5.5 (5.5.12 x86 windows).

arrays: 1.6465699672699

memory: 460400

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 1.8687851428986

memory: 363704

SplFixedArray Object
(
    [0] => aaa
    [1] => bbb
    [2] => aaabbb
)

arrays: 1.8554251194

memory: 275568

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 2.0101680755615

memory: 483656

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

Wniosek dla php 5.5

  1. W przypadku tablic PHP 5.5 jest szybsze niż PHP 5.4, w przypadku obiektów jest prawie takie samo
  2. Klasa jest wolniejsza niż Arrays dzięki optymalizacji PHP 5.5 i tablic.
  3. stdClass jest zła.
  4. Klasa nadal zużywa mniej pamięci niż Arrays. (około 30-40% mniej !!).
  5. SplFixedArray jest podobny do używania klasy, ale zużywa więcej pamięci.
magallanes
źródło
Dobra robota, dobry panie. Byłoby interesujące rozszerzenie tego na tablice zagnieżdżone, itp. Interesujące strony dla innych wydajności PHP: phpbench.com php-benchmark-script.com, ale podoba mi się, że używałeś również pamięci.
Heath N
2
W PHP7 różnica między tablicami i obiektami stała się bardziej znacząca. Twój skrypt pokazuje różnicę 30% czasu działania i 60% pamięci. To tylko moja maszyna, ale ogólna zasada: nie używaj tablic jako struktur. Zamiast tego użyj obiektów :)
KingCrunch
Czy w tym przypadku obiekty różnią się od klas?
Matt G
Dodanie do zakładek w nadziei na jakąkolwiek aktualizację PHP7. I być może nadchodzący PHP8, jeśli dotyczy. @magallanes
s3c
8

Użyłem tego kodu do „profilowania” (1000 instancji, 1000 000 odczytów / zapisów):

function p($i) {
  echo '<pre>';
  print_r($i);
  echo '</pre>';
}


$t0 = microtime(true);
for ($i=0; $i<1000; $i++) {
    $z = array();
    for ($j=0; $j<1000; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];
    }
}
echo '<p>arrays: '.(microtime(true) - $t0);
p($z);

$t0 = microtime(true);
for ($i=0; $i<1000; $i++) {
    $z = (object) null;
    for ($j=0; $j<1000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;
    }
}
echo '<p>obj: '.(microtime(true) - $t0);
p($z);

echo '<p> phpversion '.phpversion();

Wyprowadza w moim hostingu LINUX to:

arrays: 1.1085488796234

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
obj: 1.2824709415436

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
phpversion 5.2.17

więc podsumowując: obiekty są wolniejsze nawet w PHP 5.2. Nie używaj obiektów, chyba że naprawdę potrzebujesz ich funkcji oop.

Quazzle
źródło
7
od użytkownika levans stackoverflow.com/users/1473035/levans : Uruchomiłem to z 5.3.8, a obiekty były wolniejsze, 0,51839280128479 dla tablic w porównaniu z 0,85355806350708 dla obiektów. Uruchomiłem go również w wersji 5.4.13 i uzyskałem odwrotne wyniki, prawdopodobnie z powodu optymalizacji klas wykonanych w wersji 5.4, 0.6256799697876 dla tablic w porównaniu z 0,43650078773499. Wygląda więc na to, że stoły się odwróciły, a przedmioty są teraz do zrobienia.
Jean-Bernard Pellerin
1
Dobra odpowiedź, właśnie przetestowałem na XAMPP (Apache) i otrzymałem poniższe wyniki: tablice: 0.5174868106842 Array ([aaa] => aaa [bbb] => bbb [ccc] => aaabbb) obj: 0.72189617156982 stdClass Object ([aaa] => aaa [bbb] => bbb [ccc] => aaabbb) phpversion 5.4.19
ilhnctn
1
Uruchomiłem również 5.4.13, ale otrzymałem przeciwieństwo Jean-Bernarda Pellerina: Tablice: 0,5020840167999 Obiekty: 1,0378720760345 Więc nie chciałbym jeszcze angażować się w obiekty.
simontemplar
Zrobiłem kilka zmian w kodzie i Class jest szybszy niż Arrays dla php 5.4 (5.4.16 32-bitowy Windows). Podałem nową odpowiedź, która wyjaśnia przyczynę.
magallanes
Wyniki PHP 5.5.11: Tablice: 0.17430, Obiekty: 0.24183
Lex
3

Używam kodu magallanes pod php 7.0.9:

arrays: 0.19802498817444

memory: 324672

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.18602299690247

memory: 132376

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.1950249671936

memory: 348296

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

I php 7.1.3 użytkownika:

arrays: 0.59932994842529
memory: 444920
Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 0.72895789146423
memory: 164512

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 0.61777496337891
memory: 484416
stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)                      
chariothy
źródło
1
I nie zapomnij, że stdClass może używać prawdziwego klucza numerycznego. ['1' => 1] zostanie zapisane jako [1 => 1], ale możemy użyć $a=new stdClass(); $a->{1} = 1; $b=(array)$a;get real ['1' => 1].
chariothy
2
Podsumowując ... tablice są 18% szybsze, ale zużywają 2,7 razy więcej pamięci.
jchook
3

skrypt magallanesa @ PHP 7.3.5

  • SomeClass Object jest najszybszy i najlżejszy.
  • Array 1.32x prędkość. 2. 70x pamięć.
  • stdClass Object 1,65x prędkość. 2.94x pamięć.

Surowe dane wyjściowe:

arrays: 0.064794063568115
memory: 444920
Array (
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.048975944519043
memory: 164512
SomeClass Object (
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.081161022186279
memory: 484416
stdClass Object (
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
Qcho
źródło
3

Dla każdego, kto nadal jest zainteresowany tym pytaniem :) Uruchomiłem kod Quazzle na PHP 7.1 Ubuntu x64 i otrzymałem tę odpowiedź:

arrays: 0.24848890304565

memory: 444920

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.23238587379456

memory: 164512

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.24422693252563

memory: 484416

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

Wniosek

Tablica zajmuje 4 (!) Pamięć niż obiekt klasy.
Obiekt klasy nieznacznie szybszy.
stdClass still evil © magallanes :)

ShadowMad
źródło
2

Nie pokazałeś nam kodu, jak $object->valuedziała, ponieważ może być tak, że backend jest tablicą, w którym to przypadku teoretycznie użycie tablicy byłoby szybsze, ponieważ wymaga jednego wywołania funkcji mniej. Koszt wyszukiwania będzie prawdopodobnie ogromny w porównaniu z wywołaniem funkcji. Jeśli jest to zmienna, różnica będzie bardzo niewielka, ponieważ obiekty i tablice w PHP mają bardzo podobną implementację.

Jeśli patrzysz na optymalizacje, będziesz musiał profilować, aby sprawdzić, gdzie większość czasu jest używana. Podejrzewam, że zmiana obiektów na tablice nie zrobi większej różnicy.

Yacoby
źródło
Założyłem, że wartość będzie zmienną publiczną, dlatego zdecydowanie O (1), podczas gdy wyszukiwanie skrótu może nie być.
Filip Ekberg
2

Widzę, że to trochę stary post, więc pomyślałem, że go zaktualizuję. oto moje kody i statystyki, zrobione na Zend CE 5.3.21 Próbowałem przetestować całość, zapisując informacje i wycofując je.

V1: zajmuje 0,83 sek

for ($i=1; $i<1000000; $i++) {
  $a = get_one();
  $b = $a[0];
  $b = $a[1];
}

function get_one() {
  return array(1,1);
}

V2: zajmuje 3,05 sek

for ($i=1; $i<1000000; $i++) {
  $a = get_one();
  $b = $a->v;
  $b = $a->k;
}

function get_one() {
  $ret = new test();
  $ret->v = 1;
  $reb->k = 1;
  return $ret;
}

class test {
  public $v;
  public $k;
}

V3: zajmuje 1,98 sekundy (zwróć uwagę, że konstruktor poprawia wydajność)

for ($i=1; $i<1000000; $i++) {
  $a = get_one();
  $b = $a->v;
  $b = $a->k;
}

function get_one() {
  return new test(1,1);
}

class test {
  public $v;
  public $k;
  public function __construct($v, $k) {
    $this->v = $v;
    $this->k = $k;
  }
}
Nir
źródło
1

Zawsze możesz sprawdzić kod źródłowy PHP pod kątem takich mikro-funkcji.

Ale na pierwszy rzut oka żadne działanie ['value'] nie będzie szybsze, ponieważ PHP musi wykonać Lookup, gdzie znaleźć ['value'], nawet jeśli wyszukiwanie hashtable powinno być O (1), to nie jest gwarantowane. Korzystanie z indeksu tekstowego wiąże się z większym narzutem.

Jeśli obiekt zawiera tylko 1 zmienną, do której chcesz uzyskać dostęp, czyli wartość, użycie obiektu wymaga większego obciążenia.

Filip Ekberg
źródło
Jak myślisz, gdzie wyszukiwane są nieruchomości? Są też w tablicy haszującej ... (chociaż jest to mniej więcej prawdziwe tylko w bagażniku).
Artefacto
1

Cóż, zaciekawiło mnie dzisiaj w oparciu o benchmark @magallanes, więc nieco go rozszerzyłem. Podkręciłem niektóre pętle for, aby naprawdę podkreślić luki między elementami. Działa na Apache 2.4, mod_php i PHP 7.2.

Oto tabela podsumowująca, aby ułatwić wyniki:

+---------------------------+---------+-----------------+
|           Test            | Memory  |      Time       |
+---------------------------+---------+-----------------+
| Array                     | 2305848 | 9.5637300014496 |
| stdClass                  | 2505824 | 11.212271928787 |
| SomeClass                 |  164920 | 3.9636149406433 | <-- *
| AnotherClass              | 2563136 | 10.872401237488 |
| SetterClass               |  905848 | 59.879059791565 |
| SetterClassDefineReturn   |  905792 | 60.484427213669 |
| SetterClassSetFromParam   |  745792 | 62.783381223679 |
| SetterClassSetKeyAndParam |  745824 | 72.155715942383 |
+---------------------------+---------+-----------------+
* - Winner winner chicken dinner

Poniżej znajduje się zmodyfikowany skrypt. Chciałem przetestować właściwości ustawień metodami i zdefiniować typy. Byłem bardzo zaskoczony, gdy odkryłem, że użycie metod ustawiających dodaje znaczącego trafienia do kodu. Teraz przyznano, że jest to bardzo specyficzny test wydajności, w którym wiele aplikacji nawet tego nie osiągnie. Ale jeśli masz witrynę, która obsługuje 1000 / reqs / sekundę z 1000 klas, które są używane z tysiącami obiektów, możesz zobaczyć, jak może to wpłynąć na wydajność.

<?php

set_time_limit(500);

class SomeClass {
    public $aaa;
    public $bbb;
    public $ccc;
}
    
class AnotherClass {
}

class SetterClass {
    public $aaa;
    public $bbb;
    public $ccc;

    public function setAAA() {
        $this->aaa = 'aaa';
    }

    public function setBBB() {
        $this->bbb = 'bbb';
    }

    public function setCCC() {
        $this->ccc = $this->aaa.$this->bbb;
    }
}

class SetterClassDefineReturn {
    public $aaa;
    public $bbb;
    public $ccc;

    public function setAAA():void {
        $this->aaa = 'aaa';
    }

    public function setBBB():void {
        $this->bbb = 'bbb';
    }

    public function setCCC():void {
        $this->ccc = $this->aaa.$this->bbb;
    }
}

class SetterClassSetFromParam {
    public $aaa;
    public $bbb;
    public $ccc;

    public function setAAA(string $val): void {
        $this->aaa = $val;
    }

    public function setBBB(string $val): void {
        $this->bbb = $val;
    }

    public function setCCC(string $val): void {
        $this->ccc = $val;
    }
}

class SetterClassSetKeyAndParam {
    public $aaa;
    public $bbb;
    public $ccc;

    public function set(string $key, string $val): void {
        $this->{$key} = $val;
    }
}

function p($i) {
  echo '<pre>';
  print_r($i);
  echo '</pre>';
  echo '<hr>';
}

$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage(); 
for ($i=0; $i<1000; $i++) {
    $z = new SomeClass();
    for ($j=0; $j<10000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);

$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage(); 
for ($i=0; $i<5000; $i++) {
    $z = new AnotherClass();
    for ($j=0; $j<5000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);

$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage(); 
for ($i=0; $i<5000; $i++) {
    $z = new SetterClass();
    for ($j=0; $j<5000; $j++) {
        $z->setAAA();
        $z->setBBB();
        $z->setCCC();          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);

$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage(); 
for ($i=0; $i<5000; $i++) {
    $z = new SetterClassDefineReturn();
    for ($j=0; $j<5000; $j++) {
        $z->setAAA();
        $z->setBBB();
        $z->setCCC();          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);

$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage(); 
for ($i=0; $i<5000; $i++) {
    $z = new SetterClassSetFromParam();
    for ($j=0; $j<5000; $j++) {
        $z->setAAA('aaa');
        $z->setBBB('bbb');
        $z->setCCC('aaabbb');          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';

p($z);

$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage(); 
for ($i=0; $i<5000; $i++) {
    $z = new SetterClassSetKeyAndParam();
    for ($j=0; $j<5000; $j++) {
        $z->set('aaa', 'aaa');
        $z->set('bbb', 'bbb');  
        $z->set('ccc', 'aaabbb');        
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);

$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage(); 
for ($i=0; $i<5000; $i++) {
    $z = new stdClass();
    for ($j=0; $j<5000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z); 


$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage(); 
for ($i=0; $i<5000; $i++) {
    $z = [];
    for ($j=0; $j<5000; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];            
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);

A oto wyniki:

Time Taken (seconds): 3.9636149406433

Memory: 164920

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

-----

Time Taken (seconds): 10.872401237488

Memory: 2563136

AnotherClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

----

Time Taken (seconds): 59.879059791565

Memory: 905848

SetterClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

----

Time Taken (seconds): 60.484427213669

Memory: 905792

SetterClassDefineReturn Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

----

Time Taken (seconds): 62.783381223679

Memory: 745792

SetterClassSetFromParam Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

----

Time Taken (seconds): 72.155715942383

Memory: 745824

SetterClassSetKeyAndParam Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

----

Time Taken (seconds): 11.212271928787

Memory: 2505824

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

----

Time Taken (seconds): 9.5637300014496

Memory: 2305848

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

n0nag0n
źródło
0

Jeśli tablice i klasy mają taką samą wydajność, myślę, że użycie obiektów predefiniowanych klas do przechowywania / przekazywania danych biznesowych sprawiłoby, że nasz program byłby bardziej logiczny, a kod bardziej czytelny.

Dzisiaj, przy nowoczesnych ideach, takich jak Eclipse, Netbean ... bardzo wygodnie jest wiedzieć, jakie informacje niosą obiekty (predefiniowanej klasy), ale tablice nie są takie

Np .: Z tablicą

function registerCourse(array $student) {
    // Right here I don't know how a $student look like unless doing a print_r() or var_dump()
 ....
}

Z przedmiotem

class Studen {
    private $_name, $_age;
    public function getAge() {}
    public function getName() {}
    ..
}

function registerCourse(Studen $student) {
    // Right here I just Ctrl+Space $student or click "Student" and I know I can get name or age from it
    ...
}
trungnnh
źródło
Jest to sprzeczne z innymi sprawdzonymi odpowiedziami i nie ma dowodów. Jest to więc bardziej przekonanie ideologiczne niż rzeczywista odpowiedź.
bułeczki