dongxue163536 2018-02-25 18:41
浏览 68
已采纳

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

I am very much pulling my hair out after searching around on Google and this website for a very long time, and cannot seem to do this basic task (Java was very simple) but with PHP I'm having such a hard time. Can somebody please tell me what I am doing wrong. All I want is the Job class to be passed into the Person class and for them to link together but I am struggling to grasp it attempting various other routes of achieving it.

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

?>

  • 写回答

3条回答 默认 最新

  • dongluo6343 2018-02-25 19:05
    关注

    The question is, do you need to pass a Job instance - as dependency - to the Person object, if it's only about the job name - like in the following context? I would say not really:

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

    But what if more specific job details are to be assigned to a person? Then a Job instance can be used:

    /*
     * 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();
    

    Notes:

    • You should make all properties private. For the ones needed to be accessible from outside create public getters/setters, in order to ensure encapsulation.
    • You should use namespaces. In this case, since both classes are defined in the global namespace, you don't need to import any classes, e.g. use the statements beginning with the use keyword. Though, in other situations, where defining top-level namespaces and subnamespaces is needed, then you should definitely make use of import statements. They will give you a very elegant way of manipulating class names and increase the readability of your class codes. See PSR-1: Basic Coding Standard, PSR-2: Coding Style Guide, PSR-4: Autoloader.

    Now, what if a person can have multiple jobs? Then you could use a 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();
    

    The Law of Demeter, as greatly presented in The Clean Code Talks - Don't Look For Things!, specifies that you should only inject dependencies which are directly used by a class. E.g. you shouldn't pass dependencies having the role of intermediaries, e.g. which are only used to create other objects whos methods you need to call.

    In the earlier version of my answer I gave you the impression that it's false to use a Job instance in a Person object in order to assign the job name. It is correct to use a Job instance. By using it you are not breaking the LoD per se, but only the nuance of it, that you don't really need a Job instance in order to assign a job name to a Person object (as in my first example) if the job doesn't imply a more specifical case (as in the second example and in your good question in the comment).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容