Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: mały problem z dziedziczeniem
Forum PHP.pl > Forum > PHP > Object-oriented programming
kaem
Jestem nowym użytkownikiem na forum, więc może na początek się przywitam. A więc witam snitch.gif Niedawno zacząłem się uczyć PHP i napotkałem na taki oto problem: otóż mam dwie klasy, jedna dziedzicząca
CODE

class A
{
private $a1;
//...
}
class B extends A
{
var $a2;
//...
}

Potem wpisuje taki oto kod:
CODE

$b=new B();
$b->a1=11;
echo "$b->a1;";

I normalnie wyświetla mi wartość zmiennej $a1 równą 11, a przecież, z tego co wyczytałem klasa dziedzicząca nie powinna dziedziczyć pól prywatnych dry.gif Nie powinno tu być jakiegoś błędu?
revyag
A co masz w tej klasie ? To wygląda na jakby była wywoływana metoda magiczna __set, która tworzy dynamicznie pole klasy.
Poza tym jawnie nie przypiszesz wartości zmiennej prywatnej poza klasą więc z klasą rodzicem nie ma to wiele wspólnego.
kaem
Właśnie chodzi mi o to, że to przypisanie nie powinno być możliwe, bo przecież $a1 jest prywatne, czyli klasa B tego pola nie dziedziczy. A jednak $b->a1=11 wykonuje to przypisanie i wyświetla tą wartość. Nie rozumiem dlaczego tak się dzieje i nie wyświetla błędu sad.gif Jeśli chodz o funkcje __set to z tego co się zorientowałem to ustawia ona wartość pola klasy, a nie tworzy je dynamicznie. Czy nie? dry.gif
revyag
Napisałem przecież żebyś pokazał jak wygląda kod klasy B
kaem
Gdyby w tej klasie było coś istotnego mogącego wpłynąć na rozwiązanie mojego problemu to bym wrzucił. Nie chce zaśmiecać. To bez sensu, ale dobra, wrzucę kod:
Kod
<?php
class A
{
     private $a1;
     private function op1()
     {
         //echo "Op1: $this->a1
";
         echo "Op A prywatna
";
     }
}
class B extends A
{
     var $a2;
     function  op2()
     {
         echo 'Op2 B
';
     }
}
$b=new B();
$b->a1=11;
echo "$b->a1;";
?>

Jak widać nic ciekawego.
dr_bonzo
W koncu konkretny kod ktory mozna uruchomic.
Wiec tak:
- Klasa B nie posiada zadeklarowanej wlasciwosci a1 [jest ona tylko w klasie A]
- widocznie php zezwala na ustawianie zmiennych bez ich deklaracji [nie korzystam z tego wiec nie wiedzialem smile.gif] wiec $b->a1 to nie jest to samo co $a1 z klasy A [sproboj $a = new A(); $a->a1 = 'cos'; dostaniesz blad]

  1. <?php
  2. class A
  3. {
  4. private $a1;
  5. public function op1()
  6. {
  7. echo "Op1: " . $this->a1 . '<br />';
  8. //echo "Op A prywatna";
  9. }
  10.  
  11.  
  12. }
  13. class B extends A
  14. {
  15. var $a2;
  16. function op2()
  17. {
  18. echo 'Op2 B';
  19. }
  20. function op3()
  21. {
  22. echo "Op3: " . $this->a1 . '<br />';
  23. }
  24. }
  25. $b=new B();
  26. $b->a1=11;
  27. $b->samolot = "i co?";
  28. $b->op1(); // metoda klasy A, dostep do $a1 z A
  29. $b->op3(); // to samo ale z klasy B
  30. echo "VAL: " . $b->a1;
  31. ?>


Kod
Op1:
Op3: 11
VAL: 11
kaem
Hmm, no to rzeczywiście wygląda jakby PHP ustawiał te zmienne mimo, że nie były zadeklarowane:|
To trochę dziwna właściwość nawet jak na PHP. Dzięki za odp.
PS. Jakiś pomysł jak zrobić, żeby móc się odwoływać w obiekcie tylko do zadeklarowanych w danej klasie pól ?
dr_bonzo
__set() + rzucanie wyjatku
kaem
Ok, dzięki wielkie. Przejrzę sobie co nieco o tych wyjątkach i medodach __set i __get i coś zaimplementuje. Pzdr
dr_bonzo
Ewentualnie w __set() mozesz po prostu nic nie robic, zamiast rzucac wyjatka - wszystko zalezy co chcesz osiagnac smile.gif
kaem
Tak jak na początku napisałem, php'a zacząłem uczyć się niedawno i obecnie uczę się z książki rolleyes.gif Narazie niec konkretnego nie robię. Staram się ciekawsze fragmenty dokładniej zbadać i przetestować różne wariacje aarambo.gif Lepiej chyba teraz na etapie nauki dociec dlaczego coś tak działa a nie inaczej, niż potem tracić czas i nerwy przy pisaniu konkretnych projektów albo co gorsza już w pracy cool.gif W sumie sama nauka też potrafi dać nieźle po du...e biggrin.gif
Sedziwoj
Dlaczego w klasie B masz var? Przecież to kod PHP4, a nie PHP5, albo używasz public/protected/private, albo cofasz się i używasz tylko var.
kaem
Jeśli chce się używać modyfikatorów dostępu to wpisujemy public/protected/private ale już bez var. Bez tych modyfikatorów przed zmienną musi być var. Ja tak się uczyłem. U mnie jeśli nie poprzedze zmiennej varem to wywala mi następujący błąd:
CODE
Parse error: syntax error, unexpected T_VARIABLE, expecting T_FUNCTION in C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\6\index2.php
on line 14

Oczywiście używam php 5.
Sedziwoj
@kaem
Ty nie rozumiesz, var to było w PHP4, odpowiednikiem tego w PHP5 jest public (a dodatkowo masz jeszcze dwa w PHP5)
kaem
No ok, pytam bo uczę się teraz z książki niby już z wydaniem pod PHP 5 i tam jeszcze używają w klasach var. Teraz będę już pisał public. thx
Sedziwoj
http://www.php.net/manual/en/language.oop5.visibility.php
Rzuć okiem na "Note".
Z książkami jest taki kłopot, że czasem autorzy też niewiele wiedzą, albo co gorsza powtarzają to samo z PHP4, pisząc że to 5...
Ogólnie polecam korzystanie z wielu źródeł, bo co programista to inaczej to wygląda. Czytać i składać wszystko w całość.
kaem
A no właśnie. Ja już używam PHP ver. 5.2.6 i dlatego nie miałem żadnego ostrzeżenia. Myślałem, że wszystko jest git rolleyes.gif Racja - nie ufać tylko jednemu podręcznikowi
Heweliusz
Jeżeli można, chciałbym podpiąć się do tematu, mam problem odwrotny, tzn. mam klasę user, która dziedziczy po klasie session. W klasie user korzystam z właściwości klasy session, lecz mimo iż jest ona publiczna, dla klasy user jest pusta...
session.php
  1. <?php
  2. class session
  3. {
  4. public $data = array();
  5. public $session_id = '';
  6. public $session_ip = '';
  7. public $session_start_time = '';
  8. public $session_expire_time = '';
  9. public $session_user_id = 1;
  10. ?>

Chodzi o zmienną $data, domyślnie deklaruję ją jako pustą tablicę, potem w klasie session wstawiam tam dane z bazy danych.
Natomiast, chciałbym wykorzystać tą zmienną w klasie user, która dziedziczy od session.
session.php (obie są w tym samym pliku)
  1. <?php
  2. class user extends session
  3. {
  4. public $language = array();
  5. public $style_name;
  6. public $lang_path;
  7. public $style_path;
  8.  
  9. function install()
  10. {
  11. global $db, $smarty, $root_path;
  12.  
  13. if ($this->data['user_id'] != 1)
  14. {
  15. $this->style_name = $this->data['user_style'];
  16. $this->style_path = $root_path . 'styles/' . $this->style_name;
  17. }
  18. else
  19. {
  20. $this->style_name = 'default';
  21. $this->style_path = $root_path . 'styles/' . $this->style_name;
  22. }
  23. ?>

Parser zgłasza błąd poziomu notice, iż index w tablicy data nie istnieje, sprawdzałem to i okazało się że jest pusta.
Moja wersja php: 5.2.5
kwiateusz
j.w. byl juz temat o tym ze dziedziczenie ma byc logiczne, a nie po to bo Ci jakies metody z innej klasy potrzeba... jak Ci potrzeba jej metod to przekaz sobie w konstruktorze, singletonem gdzieś w srodku albo co innego tylko broń Boże przed bezsensownym dziedziczeniem...
manro
W klasie A zmienną a1 powinieneś zadeklarować słowem kluczowym protected
co będzie oznaczało że będzie ona dziedziczona i będzie ona nadal chroniona co uniemożliwi zrobienie czegoś takiego
jak $b->a1=11;

zmienne private nie są dziedziczone dlatego też w klasie B nie istnieje zmienna $a1
w momencie gdy wykonujesz $b->a1=11; metoda __set automatycznie tworzy taką zmienną
i nadaje jej status publiczny możesz to zablokować zmieniając metodę __set w taki sposób
aby uniemożliwiała tworzenie zmiennych które nie są zadeklarowane w klasie
Kod
<?php
class A
{
     protected $a1;
     private function op1()
     {
         //echo "Op1: $this->a1";
         echo "Op A prywatna";
     }
}

class B extends A
{
     public function  op2()
     {
         echo 'Op2 B';
     }
}

$b=new B();
$b->a1=11;
echo "$b->a1";
?>

Co do pytania które zostało podpięte do tematu to polecam jeszcze raz przeczytać sobie co to jest dziedziczenie,
bo widzę tutaj kompletny brak zrozumienia tematu...
Heweliusz
Cytat
Co do pytania które zostało podpięte do tematu to polecam jeszcze raz przeczytać sobie co to jest dziedziczenie,
bo widzę tutaj kompletny brak zrozumienia tematu...

Może i racja, obiektami zająłem się dopiero niedawno.
W takim razie postaram sie poradzić sobie sam z problemem winksmiley.jpg
manro
Mała podpowiedź

Klasa dziedzicząca dziedziczy publiczne i chronione właściwości i metody nie dziedziczy natomiast danych
które należą do konkretnego obiektu danej klasy...
Heweliusz
Mój skrypt wzoruje na phpbb3. Dlaczego więc podobny kod z klasy session.php działa normalnie ?
phpbb3 session.php
  1. <?php
  2. class user extends session
  3. {
  4. var $lang = array();
  5. var $help = array();
  6. var $theme = array();
  7. var $date_format;
  8. var $timezone;
  9. var $dst;
  10.  
  11. var $lang_name;
  12. var $lang_id = false;
  13. var $lang_path;
  14. var $img_lang;
  15. var $img_array = array();
  16.  
  17. /**
  18. * Setup basic user-specific items (style, language, ...)
  19. */
  20. function setup($lang_set = false, $style = false)
  21. {
  22. global $db, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache;
  23.  
  24. if ($this->data['user_id'] != ANONYMOUS)
  25. {
  26. ...
  27. ?>

Używają normalnie tablicy $data, chociaż jest ona tworzona w klasie session. To właśnie mnie męczy :/
ARJ
zauważ wywołanie klasy user
common.php
  1. <?php
  2. // Instantiate some basic classes
  3. $user = new user();
  4. $auth = new auth();
  5. $template = new template();
  6. $cache = new cache();
  7. $db = new $sql_db();
  8. ?>


index.php
  1. <?php
  2. // Start session management
  3. $user->session_begin();
  4. $auth->acl($user->data);
  5. $user->setup('viewforum');
  6. ?>


klasa user przecież dziedziczy po klasie session metodę session_begin, a tam są zapisywane dane do zmiennej data. więc klasa user ustawia sobie zmienną data.

phpbb3 nie jest dobrym przykładem do podejścia obiektowego. pisane pod php4, użycie globali oraz takie dziwne techniki jak 2 klasy w jednym pliku.
Sedziwoj
Cytat(ARJ @ 25.07.2008, 22:14:20 ) *
dziwne techniki jak 2 klasy w jednym pliku.

To jest tylko konwencja, tak jak nazewnicza, więc tego bym nie wymieniał, ale reszta jeży włos na głowie.
Heweliusz
Już wiem co było nie tak ^^
Nie zauważyłem, że klasa session jest tylko szablonem, a ja próbowałem ją inicjować osobno.
Jeżeli chodzi o zły przykład, to uważam że na początek wystarczy, potem może zacznę wzorować się na innych skryptach.
Moderatorów proszę o przyznanie punktów pomógł dla userów manro oraz ARJ za pomoc smile.gif
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.