【问题标题】:PHP Abstract Class Array Protected PropertiesPHP 抽象类数组受保护的属性
【发布时间】:2015-03-30 05:36:23
【问题描述】:

我在使用抽象类和 OOP 方面有些陌生,所以请多多包涵。
我正在尝试制作员工和客户的列表,但在打印出我的 StoreList 类中的对象数组时遇到了一些麻烦,因为它们都受到保护。
我想要做的是将 storeArray 中的值打印到一个漂亮的列表中。
现在它从 Abstract 类的 Gets 中打印出所有内容,从而使数组过时。
我将在下面包含所有代码,但由于它很长,我想在这里问这个问题。
这是我在 index.php 或 Storelistclass.php 上 var_dump 时数组输出的内容

array (size=5)
  0 => 
    object(Employee)[1]
      protected 'userId' => string '1' (length=1)
      protected 'userFirstName' => string 'Joe' (length=3)
      protected 'userLastName' => string 'Longo' (length=5)
      protected 'userTitle' => string 'Employee' (length=8)
  1 => 
    object(Customer)[2]
      protected 'userId' => string '1' (length=1)
      protected 'userFirstName' => string 'Bruce' (length=5)
      protected 'userLastName' => string 'Stark' (length=5)
      protected 'userTitle' => string 'Customer' (length=8)
  2 => 
    object(Customer)[3]
      protected 'userId' => string '2' (length=1)
      protected 'userFirstName' => string 'Tony' (length=4)
      protected 'userLastName' => string 'Wayne' (length=5)
      protected 'userTitle' => string 'Customer' (length=8)
  3 => 
    object(Customer)[4]
      protected 'userId' => string '3' (length=1)
      protected 'userFirstName' => string 'Oliver' (length=6)
      protected 'userLastName' => string 'Wilson' (length=6)
      protected 'userTitle' => string 'Customer' (length=8)
  4 => 
    object(Customer)[5]
      protected 'userId' => string '4' (length=1)
      protected 'userFirstName' => string 'Slade' (length=5)
      protected 'userLastName' => string 'Queen' (length=5)
      protected 'userTitle' => string 'Customer' (length=8)

无论我在哪里尝试创建一个 foreach 循环来遍历数组,我都会收到错误消息: 无法访问受保护的财产。

foreach($this->storeArray as $data)
{
    echo $data->userFirstName;
}

当我将 User 抽象类中的属性设为 public 时,它工作得很好,但是 Gets 会过时吗? 我应该放弃 Gets 并将它们公开,还是有其他方法?
抱歉,如果这是一个愚蠢的问题,但我真的很想解决这个问题并失败了。

非常感谢任何帮助和提示(包括更新和删除功能)!

这就是我现在拥有的所有代码。

index.php:

<?php
include("classes/Userclass.php");
include("classes/Customerclass.php");
include("classes/Employeeclass.php");
include("classes/Storelistclass.php");

$employeeOne = new Employee("1","Joe","Longo","Employee");

$customerOne = new Customer("1","Bruce","Stark","Customer");
$customerTwo = new Customer("2","Tony","Wayne","Customer");
$customerThree = new Customer("3","Oliver","Wilson","Customer");
$customerFour = new Customer("4","Slade","Queen","Customer");

$list = new Storelist($employeeOne);
$list->addCustomer($customerOne);
$list->addCustomer($customerTwo);
$list->addCustomer($customerThree);
$list->addCustomer($customerFour);
?>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <!--<link href="includes/stylesheet.css" rel="stylesheet" type="text/css"/>-->
    <title>Store List</title>
  </head>
  <body>

<h1>Test Get Customer</h1>
<p>
  <?php
    echo $customerOne->getUserTitle()." #". $customerOne->getUserId() ."'s First name is ". $customerOne->getUserFirstName() ." and Last name is ". $customerOne->getUserLastName() ."<br/>";
    echo $customerTwo->getUserTitle()." #". $customerTwo->getUserId() ."'s First name is ". $customerTwo->getUserFirstName() ." and Last name is ". $customerTwo->getUserLastName() ."<br/>";
  ?>
</p>

<h1>Test Get Employee</h1>
  <p>
  <?php 
    echo $employeeOne->getUserTitle()." #". $employeeOne->getUserId() ."'s First name is ". $employeeOne->getUserFirstName() ." and Last name is ". $employeeOne->getUserLastName() ."<br/>";
  ?>
</p>

  <h1>Storelist Foreach</h1>
    <p>
      <?php
      $listtest = $list->buildList();
      echo $listtest;
      ?>
  </p>

Customerclass.php:

class Customer extends User
{
    public function userSayHi()
    {
        return "Hello , could i get some help?";
    }
}

Employeeclass.php:

<?php

class Employee extends User
{
    public function userSayHi()
    {
        return 'Hello , how may i help u?';
    }   
}

用户类.php

<?php

abstract class User
{
    protected $userId;
    protected $userFirstName;
    protected $userLastName;
    protected $userTitle;

    public function __construct($id, $firstName, $lastName, $title) 
     {
        $this->userId = $id;
        $this->userFirstName = $firstName;
        $this->userLastName = $lastName;
        $this->userTitle = $title;
     }

    //Gets
    public function getUserId()
    {
        return $this->userId;
    }

    public function getUserFirstName()
    {
        return $this->userFirstName;
    }

    public function getUserLastName()
    {
        return $this->userLastName;
    }

    public function getUserTitle()
    {
        return $this->userTitle;
    }


    //Sets
    public function setUserId($uId)
    {
        $this->userId = $uId;
    }

    public function setUserFirstName($ufirstName)
    {
        $this->userFirstName = $ufirstName;
    }

    public function setUserLastName($ulastName)
    {
        $this->userLastName = $ulastName;
    }

    public function setUserTitle($uTitle)
    {
        $this->userTitle = $uTitle;
    }

    public abstract function userSayHi();
}

Storelistclass.php

<?php
require_once("Customerclass.php");
require_once("Employeeclass.php");


 class Storelist
 {


    public $storeArray = [];


    public function __construct(Employee $employee)
    {
        array_push($this->storeArray, $employee);
    }


    public function addCustomer(Customer $customer)
    {
        array_push($this->storeArray, $customer);
        //return $this->storeArray;
    }

    public function buildList()
    {



        foreach($this->storeArray as $storeData)
        {
            echo "First Name: ".$storeData->getUserFirstName()."<br/>";
            echo "Last Name: ".$storeData->getUserLastName()."<br/>";
            echo "Is a: ".$storeData->getUserTitle()."<br/>";
            echo "<br/>";
        }

        /*
        //ERROR : Cannot access protected property Employee::$userFirstName 
       foreach($this->storeArray as $storeData)
        {
            echo "First Name: ".$storeData->userFirstName."<br/>";
            echo "Last Name: ".$storeData->userLastName."<br/>";
            echo "Is a: ".$storeData->userTitle."<br/>";
            echo "<br/>";
        }
        */
    }

     public function delete()
     {

     }

     public function update()
     {

     }
 }

【问题讨论】:

  • 在您的Storelistclass.php 文件中,您当前有两个版本的循环。注释掉的循环是不起作用的循环 - 但未注释的循环很好。通过它们的公共getUserWhatever() 方法调用这些属性正是您应该这样做的方式,而不是修改底层abstract User 以使其成为public 属性。在 buildList() 中使用这些 getter 方法有什么你不喜欢的地方吗?
  • 不会将它们设为public,但请保持一切原样。您说“现在它从 Abstract 类的 Gets 中打印出所有内容,使数组过时”——我不确定您认为数组过时的是什么。 StoreList 在内部保留客户和员工的列表;看起来不错。
  • @MichaelBerkowski 感谢您的回复,我的老师提到使用数组(不确定它是否用于打印,虽然他没有说),但我不需要使用数组现在 Storelist 类中的更新/删除函数是空的吗?如果我无法从数组中访问属性进行打印,我也将无法编辑/删除它们(我的思考过程)。
  • 可以update()/delete() 方法中使用该数组 - 我假设 delete() 旨在从数组中删除用户。如果要修改用户属性,可以使用 StoreList 类中的 setUserWhatever() 方法进行 - 您不需要直接写入属性,因为设置器会为您处理它。尽管如此,你现在拥有的一切在我看来都还不错。
  • @MichaelBerkowski 嗯好的,但我该怎么做呢?由于我无法访问数组属性,因此我不知所措。也许我只是在这里混淆了自己,呵呵。

标签: php arrays oop properties abstract-class


【解决方案1】:

解决方案是实际使用您费力定义的 getter 方法 (getUserWhatever())。通过保持它们与protected 可见性保持原样,除了使用您定义的setUserWhatever() 方法之外,无法修改它们,因此您可以进行额外的验证(例如防止非空值)并抛出异常例如,无效数据。因此,它们不会像 public 属性那样从类外部直接可变是有用的。

在您的Storelist 类中,您已定义$storeArray 属性具有public 可见性,这意味着您可以在index.php 的类之外读取它。由于您将EmployeeCustomer 对象添加到该数组,这些对象仍然可以通过$list-&gt;storeArray 上的数组键单独寻址。因此,例如,要修改姓氏,您可以使用

// Set the 3rd user's last name
$list->storeArray[2]->setUserLastName('Jones');

同样,在Storelist 类中使用$this 也是可能的:

// Inside Storelist
$this->storeArray[2]->setUserLastName('Jones');

因此,您已经对这些课程的布局非常了解。我还可以建议一件事;因为您已经创建了通过方法调用将CustomerEmployee 对象添加到Storelist::$storeArray 的方法,而不是直接修改数组:

// You're doing this:
$list = new Storelist($employeeOne);
$list->addCustomer($customerOne);

// And not this (directly modifying storeArray):
$list = new Storelist($employeeOne);
$list->storeArray[] = $customerOne

...然后考虑将Storelist::$storeArray 定义为protected 属性,以便您可以使用其setter 方法对其进行写入。然后你还需要创建一个返回数组的getter方法。

class Storelist
{
    // This becomes protected
    protected $storeArray = [];

    // So you need a getter:
    public function getStoreArray()
    {
       return $this->storeArray;
    }
    // etc...
}

若要从index.php 修改数组,您将无法再直接读取其元素。相反,您调用它的 getter 方法:

// You can't do this:
$list->storeArray[2]->setUserLastName('Jones');

// Instead do it via the getter:
$list->getStoreArray()[2]->setUserLastName('Jones');

(注意,上面的()[2] 语法需要PHP 5.4+)

【讨论】:

    猜你喜欢
    • 2011-06-06
    • 2017-06-14
    • 1970-01-01
    • 2016-02-19
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2014-08-10
    相关资源
    最近更新 更多