【问题标题】:PHP Child class accessing Parent variable problemPHP子类访问父变量问题
【发布时间】:2009-05-06 20:21:42
【问题描述】:

我上了这门课:

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-> 不起作用,看起来就像每次我执行“new ContactInformation.. ..) PHP 创建一个“新用户名”。有机会从用户名访问当前值吗?

谢谢

【问题讨论】:

  • 我认为你需要从头开始阅读类扩展和抽象。
  • "private __construct" uff.

标签: php oop


【解决方案1】:

为什么用户名构造函数是私有的?如果您想让创建用户名成为不可能,请将用户名类抽象化。另外,不要从父类中创建新的联系信息。这是另一种说法:

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 构造函数。

【讨论】:

  • 声明一个受保护的构造函数在单例中很常见。但是在这种情况下使用 abstract 可能是正确的,因此如果您尝试创建新的 Username(); 会得到更多有用的错误;
  • 是的,这在单例模式中很常见。但是当您需要扩展单例类时,单例模式并不好使用,尤其是在 PHP 中。很多人还争辩说单例模式是有缺陷的,最好确保在应用程序中只创建一个实例,而不是以编程方式强制创建一个实例。此外,如果他想遵循单例模式,他将需要一个“getInstance”方法,并且还需要将 __clone-magic 方法设为私有。
  • 我不认为 James 建议 Singleton 在这里适用;他指出私有或受保护的构造函数具有有效用途。
【解决方案2】:

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 构造函数,该构造函数创建一个 new 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
    }
}

【讨论】:

    【解决方案3】:

    首先,当您创建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
    

    【讨论】:

      【解决方案4】:

      如果我对您的理解正确,您想从该对象中包含的对象访问该对象的属性吗?如果这是正确的,那么它是如何完成的:

      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 中,对象总是通过引用传递,除非您明确克隆它们。

      【讨论】:

      • 在这种情况下,您已经使用了组合和继承;后者是不必要的。你能澄清一下你的例子吗?
      【解决方案5】:
      <?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();
      

      【讨论】:

        猜你喜欢
        • 2011-09-21
        • 2020-02-13
        • 1970-01-01
        • 2011-04-08
        • 2012-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多