В чем разница между публичным, частным и защищенным?


Когда и почему я должен использовать public, private, и protected функции и переменные внутри класса? В чем разница между ними?

Примеры:

// Public
public $variable;
public function doSomething() {
  // ...
}

// Private
private $variable;
private function doSomething() {
  // ...
}

// Protected
protected $variable;
protected function doSomething() {
  // ...
}
Author: Edward, 2010-12-06

16 answers

Вы используете:

  • public область действия, чтобы сделать эту переменную/функцию доступной из любого места, других классов и экземпляров объекта.

  • private область действия, когда вы хотите, чтобы ваша переменная/функция была видна только в своем собственном классе.

  • protected область действия, когда вы хотите сделать свою переменную/функцию видимой во всех классах, которые расширяют текущий класс, включая родительский класс.

Подробнее: (Для всестороннего информация)

 1115
Author: Sarfraz, 2018-06-03 13:57:46

dd

Общедоступный:

Когда вы объявляете метод (функцию) или свойство (переменную) как public, к этим методам и свойствам можно получить доступ:

  • Тот же класс, который его объявил.
  • Классы, которые наследуют вышеуказанный объявленный класс.
  • Любые посторонние элементы за пределами этого класса также могут получить доступ к этим вещам.

Пример:

<?php

class GrandPa
{
    public $name='Mark Henry';  // A public variable
}

class Daddy extends GrandPa // Inherited class
{
    function displayGrandPaName()
    {
        return $this->name; // The public variable will be available to the inherited class
    }

}

// Inherited class Daddy wants to know Grandpas Name
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'

// Public variables can also be accessed outside of the class!
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Prints 'Mark Henry'

Защищено:

При объявлении метода (функция) или свойство (переменная) как protected, эти методы и свойства могут быть доступны

  • Тот же класс, который его объявил.
  • Классы, которые наследуют вышеуказанный объявленный класс.

Посторонние члены не могут получить доступ к этим переменным. "Посторонние" в том смысле, что они не являются экземплярами объектов самого объявленного класса.

Пример:

<?php

class GrandPa
{
    protected $name = 'Mark Henry';
}

class Daddy extends GrandPa
{
    function displayGrandPaName()
    {
        return $this->name;
    }

}

$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'

$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error

Точная ошибка будет такой:

PHP Фатальный ошибка: Не удается получить доступ к защищенному свойству Дедушка::$name


Личное:

Когда вы объявляете метод (функцию) или свойство (переменную) как private, к этим методам и свойствам можно получить доступ:

  • Тот же класс, который его объявил.

Посторонние члены не могут получить доступ к этим переменным. Посторонние в том смысле, что они не являются экземплярами объектов самого объявленного класса и даже классов, которые наследуют объявленный класс.

Пример:

<?php

class GrandPa
{
    private $name = 'Mark Henry';
}

class Daddy extends GrandPa
{
    function displayGrandPaName()
    {
        return $this->name;
    }

}

$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Results in a Notice 

$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error

Точные сообщения об ошибках будут следующими:

Примечание: Неопределенное свойство: Папа::$имя
Неустранимая ошибка: Не удается получить доступ к частной собственности Дедушка::$name


Анализ класса Дедушки с использованием Отражение

Эта тема на самом деле не выходит за рамки, и я добавляю ее сюда только для того, чтобы доказать, что рефлексия действительно мощна. Как я уже говорил в трех предыдущих примеры, protected и private члены (свойства и методы) не могут быть доступны за пределами класса.

Однако с помощью отражения вы можете сделать необычное, даже получив доступ protected и private участники вне класса!

Ну, а что такое отражение?

Отражение добавляет возможность перепроектировать классы, интерфейсы, функции, методы и расширения. Кроме того, они предлагают способы получения комментариев к документам для функций, классов и методов.

Преамбула

У нас есть класс с именем Grandpas и скажем, что у нас есть три свойства. Для удобства понимания рассмотрим, что есть три дедушки с именами:

  • Марк Генри
  • Джон Клэш
  • Уилл Джонс

Давайте сделаем их (назначим модификаторы) public, protected и private соответственно. Вы очень хорошо знаете, что члены protected и private не могут быть доступны за пределами класса. Теперь давайте опровергнем утверждение с использованием отражения.

Код

<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John Clash';  // This grandpa is mapped to a protected  modifier
    private    $name3 = 'Will Jones';  // This grandpa is mapped to a private modifier
}


# Scenario 1: without reflection
$granpaWithoutReflection = new GrandPas;

# Normal looping to print all the members of this class
echo "#Scenario 1: Without reflection<br>";
echo "Printing members the usual way.. (without reflection)<br>";
foreach($granpaWithoutReflection as $k=>$v)
{
    echo "The name of grandpa is $v and he resides in the variable $k<br>";
}

echo "<br>";

#Scenario 2: Using reflection

$granpa = new ReflectionClass('GrandPas'); // Pass the Grandpas class as the input for the Reflection class
$granpaNames=$granpa->getDefaultProperties(); // Gets all the properties of the Grandpas class (Even though it is a protected or private)


echo "#Scenario 2: With reflection<br>";
echo "Printing members the 'reflect' way..<br>";

foreach($granpaNames as $k=>$v)
{
    echo "The name of grandpa is $v and he resides in the variable $k<br>";
}

Выход:

#Scenario 1: Without reflection
Printing members the usual way.. (Without reflection)
The name of grandpa is Mark Henry and he resides in the variable name1

#Scenario 2: With reflection
Printing members the 'reflect' way..
The name of grandpa is Mark Henry and he resides in the variable name1
The name of grandpa is John Clash and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3

Распространенные заблуждения:

Пожалуйста, не путайте с приведенным ниже примером. Как вы все еще можете видеть, члены private и protected не могут быть доступны за пределами класса без использования отражения

<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John Clash';  // This grandpa is mapped to a protected modifier
    private    $name3 = 'Will Jones';  // This grandpa is mapped to a private modifier
}

$granpaWithoutReflections = new GrandPas;
print_r($granpaWithoutReflections);

Выход:

GrandPas Object
(
    [name1] => Mark Henry
    [name2:protected] => John Clash
    [name3:GrandPas:private] => Will Jones
)

Функции отладки

print_r, var_export и var_dump являются функциями отладчика . Они представляют информация о переменной в удобочитаемой для человека форме. Эти три функции будут раскрывать свойства protected и private объектов с PHP 5. Статические члены класса не будут показаны .


Дополнительные ресурсы:


 1046
Author: Shankar Damodaran, 2014-05-12 08:25:10

Обычно считается хорошей практикой использовать по умолчанию наименьшую требуемую видимость, поскольку это способствует инкапсуляции данных и хорошему дизайну интерфейса. При рассмотрении переменной-члена и видимости метода подумайте о роли, которую этот элемент играет во взаимодействии с другими объектами.

Если вы "кодируете интерфейс, а не реализацию", то обычно довольно просто принимать решения о видимости. Как правило, переменные должны быть закрытыми или защищенными, если вы у вас есть веская причина разоблачить их. Вместо этого используйте общедоступные средства доступа (получатели/установщики), чтобы ограничить и регулировать доступ к внутренним функциям класса.

Если использовать автомобиль в качестве аналогии, такие вещи, как скорость, передача и направление, будут частными переменными экземпляра. Вы не хотите, чтобы водитель напрямую манипулировал такими вещами, как соотношение воздуха и топлива. Вместо этого вы предоставляете ограниченное число действий в качестве общедоступных методов. Интерфейс к автомобилю может включать такие методы, как accelerate(), deccelerate()/brake(), setGear(), turnLeft(), turnRight(), и т.д.

Водитель не знает и не должен заботиться о том, как эти действия выполняются внутренними устройствами автомобиля, и раскрытие этой функциональности может быть опасным для водителя и других людей на дороге. Отсюда и хорошая практика разработки общедоступного интерфейса и инкапсуляции данных, стоящих за этим интерфейсом.

Этот подход также позволяет изменять и улучшать реализацию общедоступных методов в вашем классе, не нарушая контракт интерфейса с клиентским кодом. Для например, вы могли бы улучшить метод accelerate(), чтобы сделать его более экономичным, но использование этого метода останется прежним; клиентский код не потребует изменений, но все равно получит преимущества от повышения эффективности.

Редактировать: Поскольку, похоже, вы все еще находитесь в процессе изучения объектно-ориентированных концепций (которые гораздо сложнее освоить, чем синтаксис любого языка), я настоятельно рекомендую взять копию Объектов PHP, шаблонов и практики автор: Мэтт Зандстра. Это книга, которая впервые научила меня , как эффективно использовать ООП, а не просто учить меня синтаксису. Я изучил синтаксис за несколько лет до этого, но это было бесполезно без понимания "почему" ООП.

 82
Author: The Awnry Bear, 2012-09-03 20:24:05

Частный - доступ возможен только из класса

Защищенный - может быть доступен из класса и НАСЛЕДУЮЩИХ классов

Общедоступный - также может быть доступен из кода ЗА ПРЕДЕЛАМИ класса

Это относится как к функциям, так и к переменным.

 70
Author: Olaf, 2010-12-05 22:17:02

Разница заключается в следующем:

Public :: Общедоступная переменная или метод могут быть доступны напрямую любому пользователю класса.

Protected :: Защищенная переменная или метод не могут быть доступны пользователям класса, но могут быть доступны внутри подкласса, который наследуется от класса.

Private :: Доступ к закрытой переменной или методу возможен только изнутри класса, в котором он определен.Это означает, что закрытая переменная или метод не может быть вызван из дочернего элемента, который расширяет класс.

 24
Author: Matthew Watts, 2012-09-03 20:47:27

Области видимости с Абстрактными примерами :: Облегчает понимание

Эта видимость свойства или метода определяется путем предварительного объявления одного из трех ключевых слов (общедоступного, защищенного и частного)

Public: Если свойство или метод определены как общедоступные, это означает, что к ним можно как обращаться, так и манипулировать всем, что может ссылаться на объект.

  • Абстрактный, например. Подумайте о публичной области видимости как "публичный пикник", на который может прийти любой желающий.

Защищенный: когда для видимости свойства или метода установлено значение защищенные члены могут быть доступны только внутри самого класса и унаследованными и наследующими классами. (Наследуется: - класс может иметь все свойства и методы другого класса).

  • Подумайте о защищенной области видимости как "Корпоративный пикник", где членам компании и членам их семей разрешается не публиковаться. Это самая распространенная область применения ограничение.

Private: Когда для видимости свойства или метода установлено значение private, только класс, у которого есть закрытые члены, может получить доступ к этим методам и свойствам (внутри класса), несмотря на то, что там может быть какое-либо отношение к классу.

  • по аналогии с пикником думайте как "корпоративный пикник, на который допускаются только члены компании" на пикнике. не допускается ни семья, ни широкая общественность.
 16
Author: Suman K.C, 2014-02-07 03:19:11
/**
 * Define MyClass
 */
class MyClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // We can redeclare the public and protected method, but not private
    protected $protected = 'Protected2';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined

Извлечено Из:

Http://php.net/manual/en/language.oop5.visibility.php

 14
Author: Techie, 2013-10-03 11:01:26

⚡️ Вот простой способ запомнить объем public, protected и private.

PUBLIC:

  • public область действия: Общедоступная переменная/функция доступна как для объектов, так и для других классов.

PROTECTED:

  • protected область действия: Защищенная переменная/функция доступна для всех классов, расширяющих текущий класс.
  • Нет! Объекты не могут получить доступ к этому область применения

PRIVATE:

  • private область действия: Частная переменная/функция видна только в текущем классе, в котором она определяется.
  • Нет! Класс, расширяющий текущий класс, не может получить доступ к этой области.
  • Нет! Объекты не могут получить доступ к этой области.

Прочитайте Видимость метода или переменной в руководстве по PHP.

 9
Author: Ahmad Awais, 2017-12-11 08:02:20

Учитывая ', когда':
Я склонен изначально объявлять все частным, если я не совсем уверен. Причина в том, что обычно гораздо проще сделать частный метод общедоступным, чем наоборот. Это потому, что вы, по крайней мере, можете быть уверены, что закрытый метод не использовался нигде, кроме как в самом классе. Общедоступный метод, возможно, уже используется повсеместно, возможно, требуя обширной перезаписи.

Обновление: я выбираю значение по умолчанию protected в настоящее время, потому что я пришел к выводу, что он достаточно хорош для инкапсуляции и не мешает, когда я расширяю классы (чего я все равно стараюсь избегать). Только если у меня будет веская причина использовать два других, я это сделаю.

Веской причиной для метода private было бы то, что реализует нечто присущее этому объекту, что даже расширяющийся класс не должен меняться (фактическая причина, в дополнение к инкапсуляции, например, управление внутренним состоянием). В конце концов, это все еще достаточно легко отследить там, где обычно используется метод protected, поэтому в настоящее время я по умолчанию использую protected. Я признаю, что, возможно, не на 100% объективный опыт "в окопах".

 8
Author: DanMan, 2018-07-24 10:28:19

Руководство по PHP хорошо изучено по вопросу здесь .

Видимость свойства или метода может быть определена путем добавления в объявление префикса с ключевыми словами public, protected или private. Члены класса, объявленные общедоступными, могут быть доступны везде. Члены, объявленные защищенными, могут быть доступны только внутри самого класса, а также унаследованными и родительскими классами. Члены, объявленные как закрытые, могут быть доступны только классу, определяющему члена.

 6
Author: code_burgar, 2010-12-05 22:16:37

Для меня это самый полезный способ понять три типа свойств:

Public: Используйте это, когда вы согласны с тем, что эта переменная доступна напрямую и изменяется из любого места вашего кода.

Пример использования вне класса:

$myObject = new MyObject()
$myObject->publicVar = 'newvalue';
$pubVar = $myObject->publicVar;

Защищенный: Используйте это, когда вы хотите заставить других программистов (и себя) использовать геттеры/сеттеры за пределами класса при доступе и настройке переменных (но вы должны будьте последовательны и также используйте геттеры и сеттеры внутри класса). Это или private, как правило, используется по умолчанию для настройки всех свойств класса.

Почему? Потому что, если вы решите в какой-то момент в будущем (может быть, даже примерно через 5 минут), что вы хотите манипулировать значением, возвращаемым для этого свойства, или сделать что-то с ним перед получением/настройкой, вы можете сделать это без рефакторинга везде, где вы использовали его в своем проекте.

Пример использования извне класс:

$myObject = new MyObject()
$myObject->setProtectedVar('newvalue');
$protectedVar = $myObject->getProtectedVar();

Частный: private свойства очень похожи на свойства protected. Но отличительная особенность/отличие заключается в том, что создание private также делает его недоступным для дочерних классов без использования метода получения или установки родительского класса.

Таким образом, в принципе, если вы используете геттеры и сеттеры для свойства (или если оно используется только внутри родительского класса и не предназначено для доступа где-либо еще), вы можете также сделать это private, просто чтобы не позволяйте никому пытаться использовать его напрямую и вводить ошибки.

Пример использования внутри дочернего класса (который расширяет MyObject):

$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();
 6
Author: Andrew, 2016-01-25 18:30:39

Они существуют для обеспечения различных уровней инкапсуляции

 4
Author: Mchl, 2010-12-05 22:22:42

Переменные в PHP приводятся в трех разных типах:

Общедоступный: значения этих типов переменных доступны во всей области видимости и требуют выполнения вашего кода. объявить как: public $examTimeTable;

Private: Значения переменной этого типа доступны только для класса, к которому она принадлежит. private $classRoomComputers;

Защищено: Значения этого класса доступны только в том случае, если доступ был предоставлен в форме наследования или их дочернего класса. обычно используется :: для предоставления доступа родителю класс

protected $familyWealth;

 4
Author: star18bit, 2013-03-15 08:25:49

Возрождая старый вопрос, но я думаю, что действительно хороший способ подумать об этом - это с точки зрения API, который вы определяете.

  • public - Все, что помечено как общедоступное, является частью API, который любой, кто использует ваш класс/интерфейс/другой, будет использовать и полагаться на него.

  • protected - Не обманывайтесь, это тоже часть API! Люди могут создавать подклассы, расширять ваш код и использовать все, что помечено как защищенное.

  • private - Частные свойства и методы могут меняйтесь так сильно, как вам нравится. Никто другой не может ими пользоваться. Это единственные вещи, которые вы можете изменить, не внося кардинальных изменений.

Или в Семвер терминах:

  • Изменения в чем-либо public или protected следует рассматривать как СЕРЬЕЗНЫЕ изменения.

  • Все новое public или protected должно быть (по крайней мере) НЕЗНАЧИТЕЛЬНЫМ

  • Только новые/изменения во что-либо private могут быть ИСПРАВЛЕНЫ

Итак, с точки зрения поддержания кода, полезно быть осторожным с тем, что вы делаете public или protected, потому что это то, что вы обещаете своим пользователям.

 3
Author: mcfedr, 2016-11-16 09:51:18

Public: это состояние по умолчанию, когда вы объявляете переменную или метод, к которому можно получить доступ любым способом непосредственно к объекту.

Защищенный: Может быть доступен только в пределах объекта и подклассов.

Частный: на него можно ссылаться только внутри объекта, а не подклассов.

 1
Author: Nomadme, 2016-01-04 17:46:54

Три Уровня Видимости

В ООП PHP у нас есть три уровня видимости свойств и методов класса: общедоступный, защищенный и частный. Видимость объявляется с помощью ключевого слова visibility, чтобы указать, какой уровень видимости имеет свойство или метод. Эти три уровня определяют, можно ли получить доступ к свойству или методу за пределами класса и в классах, которые расширяют класс.

Публичный

Этот уровень не имеет ограничений, что означает он может быть вызван в любой области. Это означает, что общедоступное свойство объекта может быть как извлечено, так и изменено из любого места программы - в классе, подклассе или за пределами класса.

Защищенный

К защищенным свойствам и методам можно получить доступ изнутри класса, в котором они объявлены, или из любого класса, который их расширяет. К ним нельзя получить доступ извне класса или подкласса.

Частный

Частное свойство или метод не могут быть доступным подклассу класса, в котором он определен. Если у вас есть класс с защищенным свойством и частным свойством, а затем расширить этот класс в подклассе, вы можете получить доступ к защищенному свойству, но не к частному свойству.

 1
Author: Niby, 2018-06-05 16:12:49