it-swarm.com.ru

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

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

Примеры:

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

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

// Protected
protected $variable;
protected function doSomething() {
  // ...
}
894
Adam

Ты используешь:

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

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

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

More: (для полной информации)

1162
Sarfraz

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: невозможно получить доступ к защищенному свойству GrandPa :: $ 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
Неустранимая ошибка: невозможно получить доступ к частной собственности GrandPa :: $ name


Рассекая класс дедушки, используя Reflection

Эта тема на самом деле не выходит за рамки, и я добавляю ее сюда, чтобы доказать, что рефлексия действительно мощная. Как я уже говорил в трех приведенных выше примерах, члены 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. Статические члены класса будут отображаться not.


Больше ресурсов:


1083
Shankar Damodaran

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

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

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

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

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

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

82
The Awnry Bear

private - может быть доступен только из класса WITHIN

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

public - можно получить доступ из кода вне класса, а также

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

73
Olaf

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

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

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

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

25
Matthew Watts

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

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

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

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

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

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

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

  • с аналогией с пикником думайте как "пикник компании, где разрешены только члены компании" на пикнике. не семья и широкая публика не допускаются.
16
Suman K.C
/**
 * 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
Techie

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

PUBLIC:

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

PROTECTED:

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

PRIVATE:

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

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

11
Ahmad Awais

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

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

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

8
DanMan

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

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

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

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

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

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

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

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

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

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

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

$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();
6
Andrew

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

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

6
code_burgar

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

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

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

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

protected $familyWealth;

4
star18bit

Они там, чтобы учесть разные уровни инкапсуляции

4
Mchl

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

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

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

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

Или в Semver условия:

  • Изменения во что-либо public или protected должны рассматриваться как ОСНОВНЫЕ изменения. 

  • Все новое public или protected должно быть (как минимум) МЕНЬШИМ

  • PATCH могут быть только новые/изменения чего-либо private

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

3
mcfedr

Когда мы следуем объектно-ориентированному php в нашем проекте, мы должны следовать некоторым правилам, чтобы использовать модификаторы доступа в php. Сегодня мы собираемся четко узнать, что такое модификатор доступа и как мы можем его использовать. Модификаторы доступа PHP используются для установки прав доступа с классами PHP и их членами, которые являются функциями и переменными, определенными в области видимости класса. В php есть три области для учеников.

  1. ОБЩЕСТВЕННОЕ
  2. ЧАСТНЫЙ
  3. ЗАЩИЩЕНЫ

Теперь давайте посмотрим на следующее изображение, чтобы понять уровень доступа модификатора доступа  enter image description here

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

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

private: - члены класса с этим ключевым словом будут доступны внутри самого класса. мы не можем получить доступ к частным данным из подкласса. Он защищает членов от доступа извне класса.

protected: - то же самое как private, за исключением того, что позволяет подклассам получать доступ к защищенным членам суперкласса.

Теперь посмотрите таблицу, чтобы понять модификатор доступа. Читать статью php access modifire

1
Mahedi Hasan Durjoy

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

Защищено: Доступ к нему возможен только внутри объекта и подклассов.

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

1
Nomadme