Я думаю, что не могу правильно расширить класс PHP

ребята! Сейчас я практикую расширение класса, но я думаю, что действительно что-то упускаю.

Сначала у меня есть некоторые переменные:

$username = "antonradev";
$name = "Anton Radev";
$email = "[email protected]";
$profession = "Designer";
$job_title = "Web Design Manager";
$job_location = "Sofia";

Мой родительский класс:

class User {
    public $username;
    public $name;
    public $email;

    public function __construct($username, $name, $email) {
        $this->username = $username;
        $this->name = $name;
        $this->email = $email;
    }

}

После этого я расширяю так:

class User_Professional extends User {

    public $user_profession;
    public $user_job_title;
    public $user_work_location;

    public function __construct($user_profession, $user_job_title, $user_work_location) {
        $this->user_profession = $user_profession;
        $this->user_job_title = $user_job_title;
        $this->user_work_location = $user_work_location;
    }

}

Я создаю экземпляр:

$user_professional = new User_Professional($username, $name, $email, $profession, $job_title, $job_location);

И я пытаюсь распечатать некоторые данные:

print "The employee username is: " . $user_professional->username;

Но ничего не происходит. Пусто без ошибок:

Имя пользователя сотрудника:

Затем я делаю некоторые изменения и пытаюсь распечатать другое свойство:

print "The employee`s job title is: " . $user_professional->user_job_title;

Но я получаю данные из родительского класса. Он печатает неправильное свойство:

Должность сотрудника: Антон Радев

Это нормально? Где моя ошибка? Мне с этим не справиться. Благодарю вас!


person Liam James    schedule 13.02.2014    source источник


Ответы (4)


Вы должны вызвать конструктор класса User и передать туда 3 аргумента $username, $name, $email.

User конструктор класса:

public function __construct($username, $name, $email) {
    $this->username = $username;
    $this->name = $name;
    $this->email = $email;
}

User_Professional конструктор класса:

public function __construct($username, $name, $email, $user_profession, $user_job_title, $user_work_location) {
    parent::__construct($username, $name, $email);

    $this->user_profession = $user_profession;
    $this->user_job_title = $user_job_title;
    $this->user_work_location = $user_work_location;
}
person vikingmaster    schedule 13.02.2014
comment
Ой! Я этого не знал. Должен ли я включать в этот parent:: в каждом расширенном классе исходные родительские функции? Это справедливо только для конструкторов? Благодарю вас! - person Liam James; 13.02.2014
comment
Обычно вы всегда должны вызывать parent::__construct() в конструкторах дочерних классов. Однако родительский конструктор вызывается автоматически, если вы явно НЕ определяете конструктор в своем дочернем классе. Дополнительная информация: php.net/manual/en/language.oop5.decon .php Кроме того, не забудьте отметить мой ответ как принятый, если он будет вам полезен :) - person vikingmaster; 13.02.2014

class User_Professional extends User {

    public $user_profession;
    public $user_job_title;
    public $user_work_location;

    public function __construct($user_profession, $user_job_title, $user_work_location) {

        // Need to pass the usename, name, email
        parent::__construct($username, $name, $email);

        $this->user_profession = $user_profession;
        $this->user_job_title = $user_job_title;
        $this->user_work_location = $user_work_location;
    }

}

Альтернативный

class User {
    public $username;
    public $name;
    public $email;

    public function __construct() {
        $this->username = "antonradev";
        $this->name = "Anton Radev";
        $this->email = "[email protected]";
    }

}

И используйте в своем дочернем классе, например

class User_Professional extends User {

    public $user_profession;
    public $user_job_title;
    public $user_work_location;

    public function __construct($user_profession, $user_job_title, $user_work_location) {

        parent::__construct();

        $this->user_profession = $user_profession;
        $this->user_job_title = $user_job_title;
        $this->user_work_location = $user_work_location;
    }

}
person jogesh_pi    schedule 13.02.2014
comment
Привет! Благодарю вас! Я добавил эту строку (parent::__construct($username, $name, $email);), и я получаю три ошибки об уведомлении: неопределенная переменная... - person Liam James; 13.02.2014
comment
@AntonRadev это потому, что вам нужно передать $username, $name, $email в parent::__construct($username, $name, $email), чтобы инициировать родительский класс. - person jogesh_pi; 13.02.2014
comment
Да. Теперь конструктор моего дочернего класса является общедоступной функцией __construct($username, $name, $email, $user_profession, $user_job_title, $user_work_location). Кажется, много свойств добавляются все время везде. :( В чем тогда польза от расширения. Я снова не понимаю.. - person Liam James; 13.02.2014

Вы должны использовать композицию или примесь вместо наследования в этом случае.

person Ivan Velichko    schedule 13.02.2014
comment
Привет, Островский! Благодарю вас! Я не так далеко в книге :) И я думаю, что это не упоминается как тема. Чем отличается в этом случае? Разве наследование не является способом дать дочернему классу начальные свойства родительского, а дочерний класс получает больше свойств, которые мы можем использовать? - person Liam James; 13.02.2014
comment
Вы конечно правы и мой ответ просто немного оффтоп. Но когда вам понадобится еще один класс User*, такой как User_Father, а затем еще один, такой как User_Politician, вы сделаете все доступные комбинации таких классов (например, User_ProfessionalAndPolititian, User_FaterAndPolititian), чтобы получить все желаемые свойства в каком-то месте кода. Такого комбинаторного роста новых классов можно избежать с помощью техники композиции или миксина. - person Ivan Velichko; 13.02.2014

Вы переопределяете конструктор родителей. Вам нужно позвонить.

class User_Professional extends User {

  public $user_profession;
  public $user_job_title;
  public $user_work_location;

  public function __construct($user_profession, $user_job_title, $user_work_location) {
    parent::__constructor($username, $name, $email);

    $this->user_profession = $user_profession;
    $this->user_job_title = $user_job_title;
    $this->user_work_location = $user_work_location;
  }
}
person realshadow    schedule 13.02.2014
comment
Переопределение, а не перезапись. - person Rob Baillie; 13.02.2014
comment
Хм.. Похоже на двойную работу. Я должен каждый раз включать родительские свойства и методы. Но что, если я их не знаю? Я думал, что наследование — это способ работы с дочерним классом, не думая о родительском. Я неправильно понял идеи? - person Liam James; 13.02.2014