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条)

报告相同问题?

悬赏问题

  • ¥65 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?
  • ¥15 乘性高斯噪声在深度学习网络中的应用