Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Utworzenie obiektu z parametrami
Forum PHP.pl > Forum > Przedszkole
sadistic_son
Cześć,
mam tu taki przykładzik z artykułu z lipca 2022 i nie rozumiem dlaczego autor podał parametry klasy przy tworzeniu obiektu. W artykule nie ma tego wyjaśnione, natomiast Visual Studio Code mówi mi przy tworzeniu obiektu, że klasa nie ma żadnego konstruktora, więc zostanie wywołana bez parametru. Ok, jasne, ale więc dlaczego podano te parametry?

klasa:
  1. <?php
  2.  
  3. class GermanShepherd
  4. {
  5. //...
  6.  
  7. private $eye_color;
  8. private $dob;
  9. private $does_shed = true;
  10. private $kingdom = "Animalia";
  11. private $phylum = "Chordata";
  12. private $class = "Mammalia";
  13. private $order = "Carnivara";
  14. private $family = "Canidae";
  15. private $genus = "Canis";
  16. private $species = "Canis Lupus";
  17. private $subspecies = "Canis Lupus Familiaris";
  18. private $breed = "German Shepherd Dog";
  19. private $fur_color;
  20.  
  21. //...
  22.  
  23. /**
  24.   * @return string
  25.   */
  26. public function getEyeColor(): string
  27. {
  28. return $this->eye_color;
  29. }
  30.  
  31. /**
  32.   * @param string $eye_color
  33.   */
  34. public function setEyeColor(string $eye_color): void
  35. {
  36. $this->eye_color = $eye_color;
  37. }
  38.  
  39. /**
  40.   * @return string
  41.   */
  42. public function getDob(): string
  43. {
  44. return $this->dob;
  45. }
  46.  
  47. /**
  48.   * @param string $dob
  49.   */
  50. public function setDob(string $dob): void
  51. {
  52. $this->dob = $dob;
  53. }
  54.  
  55. /**
  56.   * @return bool
  57.   */
  58. public function isDoesShed(): bool
  59. {
  60. return $this->does_shed;
  61. }
  62.  
  63. /**
  64.   * @param bool $does_shed
  65.   */
  66. public function setDoesShed(bool $does_shed): void
  67. {
  68. $this->does_shed = $does_shed;
  69. }
  70.  
  71. /**
  72.   * @return string
  73.   */
  74. public function getFurColor(): string
  75. {
  76. return $this->fur_color;
  77. }
  78.  
  79. /**
  80.   * @param string $fur_color
  81.   */
  82. public function setFurColor(string $fur_color): void
  83. {
  84. $this->fur_color = $fur_color;
  85. }
  86.  
  87. //...
  88. }


Wywołanie:
  1. $gs_dog = new GermanShepherd("Brown", "Jan 20, 2018", "Brown");
  2. echo $gs_dog->getEyeColor();
  3. $gs_dog->setEyeColor("Blue");
  4. echo $gs_dog->getEyeColor();


W ogóle kiedy to sie odpali to wywala błąd:
Kod
Fatal error: Uncaught TypeError: GermanShepherd::getEyeColor(): Return value must be of type string, null returned in C:\xampp\htdocs\index.php:28 Stack trace: #0 C:\xampp\htdocs\index.php(91): GermanShepherd->getEyeColor() #1 {main} thrown in C:\xampp\htdocs\index.php on line 28
nospor
No widac blad autora, pewnie zapomnial o konstruktorze.
Temu tez masz potem blad
Fatal error: Uncaught TypeError: GermanShepherd::getEyeColor(): Return value must be of type string, null returned
bo probujesz pobrac eyeColor, ktory jeszcze nie zostal okreslony. Jakbys to robil w konstruktorze, co sugeruje kod, to tego bledu bys nie mial

po tym komentarzu autora
"
In the example above, we use the constructor to create a new GermanShepherd with Brown eyes.
"

Widac, ze zapomnial poprostu dodac konstruktor w artykule

choc na koncu artykulu ten konstruktor juz jest

public function __construct(string $eye_color,
string $dob,
string $fur_color)
{
$this->eye_color = $eye_color;
$this->dob = $dob;
$this->fur_color = $fur_color;
}


czytac to konca wink.gif
sadistic_son
No i teraz jest to dla mnie jasne skąd te parametry i czemu w takiej kolejności:)
Dziękuję.

PS. Ileż ja czasu natraciłem i w łeb zachodziłem co robię źle przez wszelkie błędy, literówki i niedopatrzenia w różnych artykułach i książkach sad.gif

EDIT:

Hej, tak się trochę bawię, celem lepszego zrozumienia konceptu i mam pewną zagwozdkę.
  1. class Test
  2. {
  3. private int $a;
  4. private int $b;
  5. private int $wynik;
  6.  
  7. public function __construct(int $a, int $b)
  8. {
  9. $this->a = $a;
  10. $this->b = $b;
  11. }
  12.  
  13. public function setA(int $a): void
  14. {
  15. $this->a = $a;
  16. }
  17.  
  18. public function getA(): int
  19. {
  20. return $this->a;
  21. }
  22.  
  23. public function setB(int $b): void
  24. {
  25. $this->b = $b;
  26. }
  27.  
  28. public function getB(): int
  29. {
  30. return $this->b;
  31. }
  32.  
  33. public function setWynik(): void
  34. {
  35. $this->wynik = $this->a + $this->b;
  36. }
  37.  
  38. public function getWynik(): int
  39. {
  40. return $this->wynik;
  41. }
  42.  
  43. }
Przy tak zbudowanej klasie musze podać $a i $b przy tworzeniu obiektu a konstruktor je sam stworzy. Moge więc tworzyć obiekt w taki sposób:
  1. $obj = new Test(10, 10);
  2. echo $obj->getA();
  3. echo $obj->getB();
  4. $obj->setWynik();
  5. echo $obj->getWynik();
W wyniku dostanę 10 10 20 ($a, $b, $wynik).

Ale mogę równierz zupełnie pozbyć się konstruktora, wtedy wywołanie będzie wyglądać jak poniżej, a wynik będzie ten sam:
  1. $obj = new Test();
  2. $obj->setA(10);
  3. echo $obj->getA();
  4. $obj->setB(10);
  5. echo $obj->getB();
  6. $obj->setWynik();
  7. echo $obj->getWynik();


To czy w takim wypadku konstruktor jest niezbędny? Czy mozna z niego zrezygnować i będzie to zgodne ze sztuką? I pytanie w drugą stronę - czy jeśli mam konstruktor to powinienem robić setter/getter aby było zgodnie ze sztuką. Czy to tylko czysty wybór programisty?
Salvation
Jeżeli parametry a i b mają być niezmienne w całym cyklu życia obiektu, to zostaw konstruktor i wywal settery dla nich.

Metoda `setWynik` nic mi nie mówi, więc musisz zmienić jej nazwę - na np. `calculate`. Po kodzie widać, że dodajesz, więc może lepiej `calculateSum`?
Co do gettera dla wyniku - zależy. Jeżeli operacje obliczenia są skomplikowane i czasochłonne, to przypisanie będzie dobrym rozwiązaniem. W innym przypadku, to metoda `calculate` powinna już coś zwracać.

Można jeszcze zrobić tak, że `calculate` będzie metodą prywatną, a `getWynik` będzie mieć if w środku i sprawdzać czy `->wynik` nie jest pusty. Aczkolwiek to rozwiązanie łąmie trochę SOLID.
viking
Nie do końca dobrze jest to zapisane. Brakuje wartości domyślnej dlatego jeżeli wywołasz getter przed setterem to php rzuci błędem "Typed property Test::$wynik must not be accessed before initialization". Ale tak, możesz pozbyć się konstuktora. Czasami stosuje też zapis np Test::fromArray(array $values) który inicjuje hurtem jakieś wartości.

edit: Oczywiście jeśli parametry "mają być niezmienne w całym cyklu życia obiektu" to po to powstało readonly.
sadistic_son
Rozumiem. Dzięki za wyjaśnienia.
Tak, rzeczywiście setWynik nie ma sensu bo ona liczy tylko a i b.

Cytat(viking @ 13.01.2023, 09:38:45 ) *
edit: Oczywiście jeśli parametry "mają być niezmienne w całym cyklu życia obiektu" to po to powstało readonly.
to nie lepiej użyć wtedy stałych?
nospor
Stalej nie okreslisz w konstruktorze,
Salvation
Cytat(sadistic_son @ 13.01.2023, 09:48:29 ) *
to nie lepiej użyć wtedy stałych?

Stała, to co innego niż niezmienny param klasy w całym cyklu życia obiektu.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.