Dziedziczenie w PHP

0

Cześć, mam taki problem z dziedziczeniem pól, które ustawiam dynamicznie.
Pierwsza klasa:

class A {
	public $value;

	function setValue($v){
		$this->value = $v;
	}
}
 class B extends A {

	function getValue(){
		return $this->value;
	}
}

$A = new A();
$A->setValue(1234);
$B = new B();
var_dump($B->getValue());

Czy jest możliwe, żeby w takiej konfiguracji ostatnia linia var_dump wypisała mi liczbę 1234?

1

A czemu nie sprawdzisz? Nie ma takiej możliwości. Zmienna $value musiała by być statyczna, żebyś otrzymał 1234. Poza tym polecam używać modyfikatora private/protected.

0

Przecież sprawdziłem, ale wypisuje NULL, więc stąd pytanie.
Dzięki za odpowiedź, skoro nie ma takiej możliwości, przerobiłem na zmienne statyczne. Kod poniżej dla potomnych.

 class A {
	static public $value;

	function setValue($v){
		self::$value = $v;
	}
}
 class B extends A {

	function getValue(){
		return self::$value;
	}
}

$A = new A();
$A::setValue(1234);
$B = new B();
var_dump($B->getValue());
1

A masz pojęcie do czego w ogóle służą te pola statyczne i jaka jest różnica między tymi przykładami poniżej i skąd to wszystko wynika?

class Father 
{
    protected $age;

    function setAge($age)
    {
        $this->age = $age;
    }
    
    function getAge()
    {
        return $this->age;
    }
}

class Son extends Father {}

$father = new Father();
$father->setAge(50);
$son = new Son();
$son->setAge(30);

var_dump($father->getAge(), $son->getAge());
int(50)
int(30)

vs.

 class Father 
{
    public static $age;

    function setAge($age)
    {
        self::$age = $age;
    }
    
    function getAge()
    {
        return self::$age;
    }
}

class Son extends Father {}

$father = new Father();
$father->setAge(50);
$son = new Son();
$son->setAge(30);

var_dump($father->getAge(), $son->getAge());
int(30)
int(30)

Równie dobrze można by też w przypadku ze staticami napisać:

$father = new Father();
Father::$age = 50;
$son = new Son();
Son::$age = 30; 

Czyli co, ojciec i syn mają mieć po 30 lat?

0

Fajny przykład, bardzo dobrze to opisałeś, jednak ja w przypadku dziecka nie ustawiam wartości. Robię to tylko dla rodzica i chcę tę wartość pobrać dla dziecka.

1
Brunatny Krawiec napisał(a):

Robię to tylko dla rodzica i chcę tę wartość pobrać dla dziecka.

ale Ty definiujesz 2 osobne obiekty, z których każdy ma swoją własną zmienną $value - to właśnie zasadnicza cecha programowania obiektowego, wszystkie instancje danej klasy (obiekty) są od siebie niezależne. Dziedziczenie odnosi się do definicji klasy i ewentualnie wartości początkowych. Mały przykład:

 class A {
 var $value;

 function setDefault() {
  $this->value = 1234;
 }

 function __construct() {
  $this->setDefault();
 }
}

class B extends A {
 function getValue() {
  return $this->value;
 }
}

$B = new B;
var_dump($B->getValue());
0

Bardzo przejrzysty przykład. Ale np. kiedy mam złożony skrypt to w jednej klasie mam np. dane do bazy, w innej klasie mam metody do logowania itp, a samo jądro skryptu to osobna klasa, więc takie pobieranie wartości z klas rodzica się przydaje czasem. Czy może jakoś inaczej to rozwiązać?

0

mam wrażenie, że dalej nie odróżniasz definicji klasy od obiektu. W definicji podajesz opis pól i metod jakie zawiera dana klasa, który możesz potem rozszerzyć w klasie potomnej o dodatkowe pola / metody - klasa potomna może korzystać z pól i metod rodzica - to jest właśnie dziedziczenie. Sama definicja klasy nie tworzy żadnych obiektów - robi się to używając operatora new. Możesz utworzyć wiele obiektów danej klasy, każdy z nich będzie miał takie zmienne jak w definicji klasy.

$A = new A();
$A::setValue(1234);
$B = new B();
var_dump($B->getValue());

klasa B dziedziczy po klasie A, więc obiekt $B będzie miał pole 'value', jego wartość nie ma jednak nic wspólnego z wartościami pól innych obiektów

Brunatny Krawiec napisał(a):

Ale np. kiedy mam złożony skrypt to w jednej klasie mam np. dane do bazy, w innej klasie mam metody do logowania itp, a samo jądro skryptu to osobna klasa, więc takie pobieranie wartości z klas rodzica się przydaje czasem. Czy może jakoś inaczej to rozwiązać?

nie zawsze musisz dziedziczyć po danej klasie aby z niej skorzystać, np. w definicji klasy 'Zaloguj' możesz korzystać z obiektu 'BazaDanych'

class Zaloguj {
 var $db;
 function __construct() {
  $this->db = new BazaDanych;
 }
}
0

Najprostszym sposobem będzie wykorzystanie pola statycznego, tak jak robi to m.in. Zend Framework v1.

abstract class Repository {

    private static $connection;

    /**
     * @return PDO
     */
    public static function getConnection()
    {
        return self::$connection;
    }

    /**
     * @param PDO $connection
     */
    public static function setConnection(PDO $connection)
    {
        self::$connection = $connection;
    }
}

class UserRepository extends Repository {

    public function findAll() {
        $sql = "SELECT * FROM users";
        $stmt = self::getConnection()->prepare($sql);
        $stmt->execute();

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function findById($id) {
        $sql = "SELECT * FROM users WHERE id = :id";
        $stmt = self::getConnection()->prepare($sql);

        $stmt->bindValue(":id", $id);
        $stmt->execute();

        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
}

// gdzieś w bootstrap.php
$pdo = new PDO("...");
Repository::setConnection($pdo);

// w twoim LoginController
$repository = new UserRepository();
$users = $repository->findAll();

$userWithId15 = $repository->findById(15);

Jest jeszcze coś takiego jak Dependency Injection Container, ale to musisz mieć już spore pojęcie o interfejsach itd. Na dobry początek to co wyżej wystarczy.

Dobra praktyką, która już mozesz stosować jest tez wstrzykiwanie zależności, czyli nie robimy new PDO w samym Repository, tylko wstrzykujemy PDO z zewnątrz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1