PHP将类传递给另一个类构造函数

时间:2018-02-25 18:41:22

标签: php oop

我在谷歌和这个网站上搜索很长一段时间之后,我非常想把头发拉出来,似乎无法做这个基本任务(Java非常简单)但是用PHP我很难过。 有人可以告诉我我做错了什么。我想要的是将Job类传递给Person类并让它们链接在一起,但我正在努力抓住它尝试各种其他实现它的路径。

<?php

class Person{
    public $name;

    public function __construct($name, Job $job){
        $this->name = $name;
        $this->job = $job;
    }

    public function display(){
        return $this->name . $this->job;
    }
}

class Job{
    public $job;

    public function __construct($job){
        $this->job = $job;
    }
}

$job = new Job("Programmer");
$person = new Person("John");

echo $person->display();

&GT;

3 个答案:

答案 0 :(得分:1)

试试这个:

<?php

class Person
{
    public $name;

    public function __construct($name, \Job $job)
    {
        $this->name = $name;
        $this->job  = $job;
    }

    public function display()
    {
        return $this->name . $this->job;
    }
}

class Job
{
    public $job;

    public function __construct($job)
    {
        $this->job = $job;
    }

    public function __toString()
    {
        return $this->job;
    }
}

$job    = new Job("Programmer");
$person = new Person("John", $job);

echo $person->display();

答案 1 :(得分:0)

问题是,您是否需要将作业实例 - 作为依赖项 - 传递给 Person 对象,如果它只是关于作业名称 - 如下所示背景?我不会说真的:

class Person {

    /**
     * Person name.
     *
     * @var string
     */
    private $name;

    /**
     * Job name.
     *
     * @var string
     */
    private $job;

    /**
     * Person's age.
     *
     * @var int
     */
    private $age;

    /**
     * Person's place of birth.
     *
     * @var string
     */
    private $birthPlace;

    /**
     * Job name.
     *
     * @param string $name Person name.
     * @param string $job Job name.
     * @param int $age Person's age.
     * @param string $birthPlace Person's place of birth.
     */
    public function __construct(string $name, string $job, int age, string $birthPlace) {
        $this->name = $name;
        $this->job = $job;
        $this->age = $age;
        $this->birthPlace = $birthPlace;
    }

    /**
     * Get person's details.
     * 
     * @return string
     */
    public function getDetails() {
        return $this->name . ', ' . $this->job . ', ' . $this->age . ', ' . $this->birthPlace;
    }

}

use Person;

$person = new Person('TLG', 'programmer', 28, 'Paris');

echo $person->getDetails();

但是如果要为一个人分配更具体的工作细节呢?然后可以使用 Job 实例:

/*
 * Job.
 */

class Job {

    /**
     * Job name.
     *
     * @var string
     */
    private $name;

    /**
     * Job location.
     *
     * @var string
     */
    private $location;

    /**
     * 
     * @param string $name Job name.
     * @param string $location Job location.
     */
    public function __construct(string $name, string $location) {
        $this->name = $name;
        $this->location = $location;
    }

    /**
     * Get the job name.
     * 
     * @return string
     */
    public function getName() {
        return $this->name;
    }

    /**
     * Get the job location.
     * 
     * @return string
     */
    public function getLocation() {
        return $this->location;
    }

}


/*
 * Person.
 */

use Job;

class Person {

    /**
     * Person name.
     *
     * @var string
     */
    private $name;

    /**
     * Job instance.
     *
     * @var Job
     */
    private $job;

    /**
     * 
     * @param string $name Person name.
     * @param Job $job Job instance.
     */
    public function __construct(string $name, Job $job) {
        $this->name = $name;
        $this->job = $job;
    }

    /**
     * Get person's details.
     * 
     * @return string
     */
    public function getDetails() {
        return $this->name . ', ' . $this->job->getName() . ' in ' . $this->job->getLocation();
    }

}


/*
 * The call.
 */

use Job;
use Person;

$job = new Job('Programmer', 'London');
$person = new Person('John', $job);

echo $person->getDetails();

备注:

  • 您应该将所有属性设为私有。对于需要从外部访问的内容,请创建公共 getters / setters ,以确保encapsulation
  • 您应该使用名称空间。在这种情况下,由于两个类都是在global namespace中定义的,因此您无需导入任何类,例如使用以 use 关键字开头的语句。但是,在其他需要定义顶级命名空间子命名空间的情况下,您绝对应该使用import语句。它们将为您提供一种非常优雅的方法来操作类名并提高类代码的可读性。请参阅PSR-1: Basic Coding StandardPSR-2: Coding Style GuidePSR-4: Autoloader

现在,如果一个人可以有多个工作怎么办?然后你可以使用 JobCollection

 /*
 * Job.
 */

class Job {

    // Same as above...

}


/*
 * Job collection.
 */

use Job;

class JobCollection {

    /**
     * Jobs list.
     *
     * @var Job[]
     */
    private $jobs = [];

    /**
     * Add a job.
     * 
     * @return $this
     */
    public function add(Job $job) {
        $this->jobs[] = $job;
        return $this;
    }

    /**
     * Get all jobs.
     * 
     * @return Job[]
     */
    public function all() {
        return $this->jobs;
    }

}


/*
 * Person.
 */

use JobCollection;

class Person {

    /**
     * Person name.
     *
     * @var string
     */
    private $name;

    /**
     * Job collection.
     *
     * @var JobCollection
     */
    private $jobs;

    /**
     * 
     * @param string $name Person name.
     * @param JobCollection $jobs Job collection.
     */
    public function __construct(string $name, JobCollection $jobs) {
        $this->name = $name;
        $this->jobs = $jobs;
    }

    /**
     * Get the person name.
     * 
     * @return string
     */
    public function getName() {
        return $this->name;
    }

    /**
     * Get the person's jobs.
     * 
     * @return Job[]
     */
    public function getJobs() {
        return $this->jobs->all();
    }

    /**
     * Get person's details.
     * 
     * @return string
     */
    public function getDetails() {
        $result = $this->getName() . '<br/>';

        foreach ($this->jobs->all() as $job) {
            $result .= $job->getName() . ' in ' . $job->getLocation() . '<br/>';
        }

        return $result;
    }

}


/*
 * The call.
 */

use Job;
use Person;
use JobCollection;

// Create some jobs.
$job1 = new Job('Programmer', 'London');
$job2 = new Job('Bartender', 'Paris');

// Create the job collection and add the jobs to it.
$jobs = new JobCollection();
$jobs
        ->add($job1)
        ->add($job2)
;

// Create the person.
$person = new Person('John', $jobs);

echo $person->getDetails();

Law of Demeter中提到的The Clean Code Talks - Don't Look For Things!指定您应该只注入类直接使用的依赖项。例如。你不应该传递具有中间人角色的依赖关系,例如:它们仅用于创建需要调用方法的其他对象。

在我的回答的早期版本中,我给你的印象是,在 Person 对象中使用 Job 实例以分配作业名称是错误的。使用 Job 实例是正确的。通过使用它,您不会破坏 LoD 本身,而只是它的细微差别,您实际上并不需要作业实例来分配作业名称如果作业并不意味着更具体的情况(如第二个例子和评论中的好问题),那么 Person 对象(如我的第一个例子中所示)。

答案 2 :(得分:0)

您在Person类中缺少Job对象,然后您应该将Job传递分配给作业变量上的Person对象。
例如:

<?php

class Person
{
    public $name;
    private $job;

    public function __construct($name, Job $job)
    {
        $this->name = $name;
        $this->job  = $job;
    }

    public function display()
    {
        return $this->name ." ". $this->job->job;
    }
}

class Job
{
    public $job;

    public function __construct($job)
    {
        $this->job = $job;
    }

}

$job = new Job("Programmer");
$person = new Person("John", $job);

echo $person->display();

&GT;