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


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

примеры:

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

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

// Protected
protected $variable;
protected function doSomething() {
  // ...
}
16 858

16 ответов:

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

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

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

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

Подробнее: (для получения полной информации)

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:

при объявлении метода (функции) или свойства (переменной) как 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
Неустранимая ошибка: не удается доступ к частной собственности дедушка::$name


рассечение класса дедушка с помощью отражение

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

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

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

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

преамбула

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

  • Марк Генри
  • John Clash
  • Будем Джонс

сделаем их (назначим модификаторы)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 are функции отладчика. Они представляют информацию о переменной в удобочитаемом виде. Эти три функции покажут protected и private свойства объектов с PHP 5. Статические члены класса будут не быть показано.


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


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

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

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

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

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

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

private-можно получить доступ только из класса

protected-можно получить доступ из класса и наследующих классов

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

PUBLIC:

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

PROTECTED:

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

PRIVATE:

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

читать видимость метода или переменной на PHP Manual.

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

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

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

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

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

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

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

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

$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();

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

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

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

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

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

protected $familyWealth;

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

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

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

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

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

  • изменения к чему-либо public или protected следует рассматривать основные изменения.

  • ничего нового public или protected должно быть (по крайней мере) незначительные

  • только новые / изменения в чем-либо private может быть патч

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

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

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

Private: можно ссылаться только на объект, а не на подклассы.

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

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

Public

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

защищенный

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

Private

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