anton_reut
@anton_reut
Начинающий веб-разработчик

Для чего объявлять (создавать) имена полей в начале класса если они же по сути объявляются (создаются) в конструкторе?

Например вот такой код:
<?php
class Testclass{
	
	private $a;
	private $b;
	
	public function __construct($a, $b){
		$this->a = $a;
		$this->b = $b;
	}
}


В конструкторе мы задаем значения переменных $a и $b, но даже если я уберу первые две строки private $a; private $b; в начале класса то эти поля автоматически создадутся из конструктора и внутренний метод нормально сработает:
class Testclass{
	
	//Закомментировал private $a;
	//Закомментировал private $b;
	
	public function __construct($a, $b){
		$this->a = $a;
		$this->b = $b;
	}
	public function Sum(){
		echo $this->a + $this->b;
	}
}
	
$object = new Testclass(5, 6);
$object->Sum();
  • Вопрос задан
  • 454 просмотра
Пригласить эксперта
Ответы на вопрос 4
@rfm
чтобы в редакторе кода, когда вы набираете
$object->|
он мог вам подсказать какие свойства есть у объекта.

чтобы явно указать видимость свойств (например, протектед)
чтобы потом не искать какие свойства есть у объекта через год, шарясь по всем его методам.
чтобы у вас не отвалилось все к чертям, если вы перепишите конструктор в классе-потомке.
Ответ написан
@FanatPHP
Зачем мыть руки перед едой, ведь и из грязных ложка не выпадет?

Пхп - язык с плохой наследственностью. И эта "возможность" - один из рудиментов оставшихся с тех времён, когда язык писался в памперсы.

Но на самом деле все переменные надо объявлять перед использованием
Ответ написан
Compolomus
@Compolomus
Комполом-быдлокодер
Это работает, сделано это для магических приколов, чтоб не было приколов лучше объявить все, если свойства нужны только в конструкторе, то их можно не создавать, а обработать конструктор и сохранить результат в свойство например
Ну и свойства такие будут публичными
Ответ написан
@yaroslavche
Тут используются области видимости: публичная (public), защищенная (protected) и приватная private. Зачем? - всё просто. Публичные свойства и методы доступны всем, кто может обратится к классу. Защищенные - только сам класс и его наследники. Приватные - только класс и больше никто.
В Вашем примере Вы создаете приватные свойства и устанавливаете значения в конструкторе.
<?php
class TestClass{
  
  private $a;
  private $b;
  
  public function __construct($a, $b){
    $this->a = $a;
    $this->b = $b;
  }
}

В таком случае свойства $a и $b будут недоступны. Например:
$testClass = new TestClass(1, 2);
echo $testClass->a; // PHP Fatal error:  Uncaught Error: Cannot access private property TestClass::$a


Когда же Вы закомментируете свойства - они динамически инициализируются в конструкторе и станут публичными, что будет означать, что любой сможет читать и изменять эти свойства:
class TestClass{
  
  public function __construct($a, $b){
    $this->a = $a;
    $this->b = $b;
  }
}

$testClass = new TestClass(1, 2);
$testClass->a = 4;
echo $testClass->a; // 4, что как бы не очень

Для этого принято хранить свойства в приватной области и писать для них геттеры/сеттеры. Например:
<?php
declare(strict_types=1);

class TestClass
{
    /** @var int $a */
    private $a;

    public function __construct(int $a, string $b)
    {
        $this->a = $a; // private
        $this->b = $b; // public
    }

    /**
     * @return int
     */
    public function getA(): int
    {
        return $this->a;
    }

    /**
     * @param int $a
     * @return TestClass
     */
    public function setA(int $a): TestClass
    {
        $this->a = $a;
        return $this;
    }
}

$testClass = new TestClass(1, "b");
$testClass->b = [];
echo $testClass->b . PHP_EOL;
$testClass->setA(2);
echo $testClass->getA() . PHP_EOL;
echo $testClass->a; // PHP Fatal error:  Uncaught Error: Cannot access private property TestClass::$a

Так же обратите внимание, что в конструкторе $b должен быть чётко строкой, но в публичное свойство я могу записать что угодно. Допустим, Ваш класс имеет метод суммы. Но если я засуну в $b массив - результат будет совсем не тем, что вы ожидаете.

И вот еще пример с protected. Напомню, что protected от private отличается тем, что private - видим только внутри класса которого определен. protected - самому классу, наследующим его классам и родительским классам.
<?php
declare(strict_types=1);

class ParentClass
{
    /** @var string|null $protected */
    protected $protected;

    public function __construct(?string $protected)
    {
        $this->protected = $protected;
    }

    /** final method */
    final public function getProtected(): ?string
    {
        return $this->protected;
    }
}

/** final class */
final class ChildClass extends ParentClass
{
    public function __construct(?string $protected)
    {
        parent::__construct($protected);
    }

    /**
     * так нельзя, потому что ParentClass::getProtected - final, что значит, что его нельзя переопределять
     * если раскомментировать: PHP Fatal error:  Cannot override final method ParentClass::getProtected()
     * но у класса ChildClass всё равно будет метод getProtected, т.к. он наследуется от ParentClass
     */
    /*
    public function getProtected(): ?string {}
    */

    /**
     * Зато можно установаить $protected, не давая возможности изменения напрямую по ссылке
     */
    public function setProtected(?string $protected): self
    {
        $this->protected = $protected;
        return $this;
    }
}

/**
 * Так нельзя, потому что ChildClass - final, что означает, что его нельзя использовать в качестве родительского класса
 * если раскомментировать: PHP Fatal error:  Class ChildChildClass may not inherit from final class (ChildClass)
 */
// class ChildChildClass extends ChildClass {}

$parentClass = new ParentClass('parent protected');
echo $parentClass->getProtected() . PHP_EOL; // parent protected

$childClass = new ChildClass('child protected');
echo $childClass->getProtected() . PHP_EOL; // child protected
/** только у ChildClass есть возможность изменить $protected, в базовом классе такого функционала нет */
$childClass->setProtected('changed child protected');
echo $childClass->getProtected() . PHP_EOL; // changed child protected

// echo $parentClass->protected; // PHP Fatal error:  Uncaught Error: Cannot access protected property ParentClass::$protected
// echo $childClass->protected; // PHP Fatal error:  Uncaught Error: Cannot access protected property ChildClass::$protected

Собственно, методы так же могут быть публичными, защищенными и приватными. И иметь такое же поведение, как и свойства.
class MyClass
{
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;

    public function getPrivate()
    {
        return $this->privateProperty;
    }

    protected function setProtectedProperty($protectedProperty)
    {
        $this->protectedProperty = $protectedProperty;
        $this->someMethod(); // PRIVATE METHOD CALL OK
        return $this;
    }

    private function someMethod()
    {
    }
}

$myClass = new MyClass();
$myClass->publicProperty = 1; // SET PUBLIC OK
$x = $myClass->publicProperty; // GET PUBLIC OK
$myClass->protectedProperty = 2; // SET PROTECTED ERROR
$myClass->setProtectedProperty(2); // SET PROTECTED ERROR - CALL PROTECTED METHOD
$y = $myClass->protectedProperty; // GET PROTECTED ERROR
$myClass->privateProperty = 2; // SET PRIVATE ERROR
$z = $myClass->privateProperty; // GET PRIVATE ERROR
$z = $myClass->getPrivate(); // GET PRIVATE OK - CALL PUBLIC METHOD
$myClass->someMethod(); // ERROR - CALL PRIVATE METHOD
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
от 55 000 до 80 000 руб.
X-Cart Ульяновск
от 80 000 до 150 000 руб.
от 150 000 до 180 000 руб.
24 авг. 2019, в 21:24
300 руб./за проект
24 авг. 2019, в 20:50
780 руб./в час
24 авг. 2019, в 19:17
5000 руб./за проект