12 Stimmen

PHP Child-Klasse greift auf Parent-Variable Problem

Ich habe diesen Kurs:

Class Username {
protected $id;
protected $username;
protected $contact_information;

     private __construct($id) {
       $this->id = (int) $id; // Forces it to be a string
       $contact_information = new ContactInformation($this->id);
     }
}

Class ContactInformation extends Username {
    protected $mobile;
    protected $email;
    protected $nextel_id;
    .....
}

Mein Problem ist: Ich möchte die $id und $username (und viele andere Variablen) auf ContactInformation zugreifen, aber parent:: oder $this-> funktioniert nicht, sieht aus wie everytime ich tun "neue ContactInformation....) PHP erstellt einen "neuen Benutzernamen". Gibt es eine Möglichkeit, auf die AKTUELLEN Werte von Username zuzugreifen?

Gracias

4 Stimmen

Ich denke, Sie müssen Klassenerweiterung und Abstraktion von Grund auf lesen.

1 Stimmen

"private __construct" uff.

12voto

PatrikAkerstrand Punkte 44499

Warum ist der Konstruktor Benutzername privat? Wenn Sie es unmöglich machen wollen, einen Benutzernamen zu erstellen, machen Sie die Klasse Username abstrakt. Außerdem sollten Sie KEINE neuen Kontaktinformationen aus der übergeordneten Klasse erstellen. Man kann es auch anders ausdrücken:

abstract class Username {
   protected $id;
   protected $username;

   public __construct($id) {
      $this->id = (int) $id; // Forces it to be a string
   }
}

class ContactInformation extends Username {
    protected $mobile;
    protected $email;
    protected $nextel_id;
    public __construct($id, $mobile, $email, $nextel_id) {
       parent::__construct($id)
       $this->mobile = $mobile;
       ....
    }
}

Anstatt den Benutzernamen direkt zu instanziieren (was jetzt unmöglich ist), erstellen Sie stattdessen eine ContactInformation. ContactInformation ruft dann den Username-Konstruktor in seinem eigenen Konstruktor auf.

0 Stimmen

Die Deklaration eines geschützten Konstruktors ist bei Singletons üblich. Aber Sie haben wahrscheinlich Recht mit der Verwendung von abstrakt in diesem Fall, so dass Sie mehr nützliche Fehler erhalten würden, wenn Sie versuchen, einen neuen Benutzernamen() zu erstellen;

0 Stimmen

Ja, es ist richtig, dass dies im Singleton-Muster üblich ist. Aber das Singleton-Muster ist nicht gut zu gebrauchen, wenn man die Singleton-Klasse erweitern muss, besonders nicht in PHP. Viele Leute argumentieren auch, dass das Singleton-Muster fehlerhaft ist und dass es besser ist, dafür zu sorgen, dass in der Anwendung nur eine einzige Instanz erzeugt wird, anstatt sie programmatisch zu erzwingen. Wenn er dem Singleton-Muster folgen will, braucht er außerdem eine "getInstance"-Methode und muss die __clone-magic-Methode privat machen.

0 Stimmen

Ich glaube nicht, dass James damit andeuten wollte, dass Singleton hier anwendbar ist; er wollte darauf hinweisen, dass ein privater oder geschützter Konstruktor durchaus seinen Nutzen hat.

8voto

James Socol Punkte 1777

Die Methode parent:: wird nur für den Zugriff auf übergeordnete Methoden verwendet, die Sie in Ihrer Unterklasse überschrieben haben, oder auf statische Variablen wie:

class Base
{
    protected static $me;

    public function __construct ()
    {
        self::$me = 'the base';
    }

    public function who() {
        echo self::$me;
    }
}

class Child extends Base
{
    protected static $me;

    public function __construct ()
    {
        parent::__construct();
        self::$me = 'the child extends '.parent::$me;
    }

    // until PHP 5.3, will need to redeclare this
    public function who() {
        echo self::$me;
    }
}

$objA = new Base;
$objA->who(); // "the base"

$objB = new Child;
$objB->who(); // "the child extends the base"

Sie wollen wahrscheinlich eine richtige Unterklasse. Erstellen Sie keine Unterklasse im Konstruktor der Basisklasse, das stellt alle Arten von OOP-Best-Practices auf den Kopf (lose Kopplung usw.) und erzeugt eine Endlosschleife. (new ContactInformation() ruft den Username-Konstruktor auf, der eine neue ContactInformation() erzeugt, die...).

Wenn Sie eine Unterklasse wünschen, etwa so:

/**
 * Stores basic user information
 */
class User
{
    protected $id;
    protected $username;

    // You could make this protected if you only wanted
    // the subclasses to be instantiated
    public function __construct ( $id )
    {
        $this->id = (int)$id; // cast to INT, not string

        // probably find the username, right?
    }
}

/**
 * Access to a user's contact information
 */
class ContactInformation extends User
{
    protected $mobile;
    protected $email;
    protected $nextel;

    // We're overriding the constructor...
    public function __construct ( $id )
    {
        // ... so we need to call the parent's
        // constructor.
        parent::__construct($id);

        // fetch the additional contact information
    }
}

Oder Sie könnten einen Delegaten verwenden, aber dann hätten die ContactInformation-Methoden keinen direkten Zugriff auf die Username-Eigenschaften.

class Username
{
    protected $id;
    protected $contact_information;

    public function __construct($id)
    {
        $this->id = (int)$id;
        $this->contact_information = new ContactInformation($this->id);
    }
}

class ContactInformation // no inheritance here!
{
    protected $user_id;
    protected $mobile;

    public function __construct($id)
    {
        $this->user_id = (int)$id;
        // and so on
    }
}

2voto

Powerlord Punkte 84404

Erstens, wenn Sie eine ContactInformation enthält sie auch alle nicht-privaten Eigenschaften und Methoden von Username . Sie benötigen keine separate Username Instanz.

Class Username {
    protected $id;
    protected $username;

    protected __construct($id) {
        $this->id = (int) $id; // Forces it to be a string
    }
}

Class ContactInformation extends Username {
    protected $mobile;
    protected $email;
    protected $nextel_id;
    // Pretend that these are here because they're defined in my parent
    //protected $id;
    //protected $username;

    public __construct($id) {
        parent::__construct($id);
        echo $this->id; //Should echo 1
    }
}

Da jedoch alle Felder geschützt sind, wird dies nicht funktionieren:

$contact_information = new ContactInformation(1); // Works fine
echo $contact_information->id;
// Whoops, visibility error because id isn't public

1voto

Jonathan Hanson Punkte 3893

Wenn ich Sie richtig verstehe, möchten Sie auf Eigenschaften eines Objekts von einem in diesem Objekt enthaltenen Objekt aus zugreifen? Wenn das richtig ist, wird es folgendermaßen gemacht:

class A {

  // These are the properties you want to access from the child object
  public $property_a;
  public $property_b;
  public $property_c;

  // This is the child object variable
  public $child_object;

  public function __construct( ) {

    // Pass 'this' into the child so that the child has a reference back to the parent
    $this->child_object = new B($this);
  }
}

class B {

  // Holds a reference to the parent object
  protected $parent_object;

  public function __construct( $object ) {

    // Remember the reference to the parent object
    $this->parent_object = $object;
  }

  // Just a Demonstration Method
  public print_parent_property_a()
  {
    // Reach into the referred parent object, and get it's property
    print $this->parent_object->property_a;
  }
}

Wenn Sie das also tun würden:

$my_object = new A();
$my_object->property_a = 'test_value';
$my_object->child_object->print_parent_property_a();

Sie würden 'test_value' erhalten

Es ist etwas anders als in Ihrem Beispiel, da die Eigenschaften der Elternklasse öffentlich sein müssen, damit das Kind auf sie zugreifen kann.

Das alles funktioniert, weil in PHP Objekte immer per Referenz übergeben werden, es sei denn, Sie klonen sie explizit.

0 Stimmen

Sie haben in diesem Fall sowohl Komposition als auch Vererbung verwendet; letztere ist unnötig. Können Sie Ihr Beispiel erläutern?

0voto

Zoyeb Shaikh Punkte 174
<?php

 abstract class employee
{ 
    //create member variable in parent class

    protected $name;
    protected $id;
    protected $mobile;  

    //constructor of parent class 
    public function __construct($n , $i , $m)
    {
        $this->name=$n;
        $this->id=$i;
        $this->mobile=$m;
    }
    //create method will return name
    public function ShowFullName()
    {

        return $this->name;
    }
//create method will return contact
    public function ShowContact()
    {

        return $this->mobile;
    }

}

class FulltimeEmployee extends employee
{

    private $days;
    private $salary;

        //create child constructor 
    public function __construct($n , $i , $mo , $d , $s)
    {
        $this->days=$d;
        $this->salary=$s;

        //calling parent constructor now we can use parent class member while calling child class constructor
        parent::__construct($n , $i , $mo);
    }

    public function calculate()
    {

        return $this->salary * $this->days;

    }
}

//providing data to child class constructor including parent class values
$child = new FulltimeEmployee("james",120,9033474118 , 2 , 200);
echo $child->calculate();
echo $child->ShowFullName();

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X