PHP子类访问父变量问题

时间:2009-05-06 20:21:42

标签: php oop

我上了这堂课:

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;
    .....
}

我的问题是:我想在ContactInformation上访问$ id和$ username(以及许多其他变量),但是parent ::或$ this->不起作用,看起来每次我做“新的ContactInformation ....”PHP创建一个“新用户名”。有机会从用户名访问CURRENT值吗?

由于

5 个答案:

答案 0 :(得分:12)

为什么Username构造函数是私有的?如果您的意思是无法创建用户名,请将Username类设为abstract。另外,请勿从父类中创建新的联系信息。这是另一种说法:

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;
       ....
    }
}

现在,您不是直接实例化用户名(现在不可能),而是创建一个ContactInformation。然后,ContactInformation在其自己的构造函数中调用Username构造函数。

答案 1 :(得分:8)

parent ::方法仅用于访问已在子类中重写的父方法,或静态变量,如:

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"

你可能想要一个合适的子类。不要在基类的构造函数中创建子类,这会将各种OOP最佳实践颠倒(松散耦合等),同时还会创建无限循环。 (new ContactInformation()调用Username构造函数,该构造函数创建一个新的ContactInformation(),其中...)。

如果你想要一个子类,可以这样:

/**
 * 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
    }
}

或者你可以使用委托,但是ContactInformation方法不能直接访问用户名属性。

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
    }
}

答案 2 :(得分:2)

首先,当您创建ContactInformation时,它还包含Username的所有非私有属性和方法。您不需要单独的Username实例。

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
    }
}

但是,由于所有字段都受到保护,因此不起作用:

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

答案 3 :(得分:1)

如果我理解正确,您想要从该对象中包含的对象访问对象的属性?如果这是正确的,这就是它的完成方式:

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;
  }
}

所以,如果你这样做:

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

你会得到'test_value'

它与您的示例略有不同,因为您需要将父类属性设置为公共,以便子级可以访问它们。

这一切都有效,因为在PHP中,对象总是通过引用传递,除非你明确克隆它们。

答案 4 :(得分:0)

<?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();