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

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

примеры:

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

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

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

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

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

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


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

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

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

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

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

преамбула

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

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

сделаем их (назначим модификаторы)public, protected и private соответственно. Ты прекрасно знаешь, что ... --8--> и 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. Статические члены класса будут не быть показано.


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



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

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

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

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

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

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


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

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

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

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


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

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

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

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


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

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

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

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

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

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

личные : когда видимость свойства или метода установлена в 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


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

PUBLIC:

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

PROTECTED:

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

PRIVATE:

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

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


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

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

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


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

видимость свойства или метода может быть определена путем префикса объявления с ключевыми словами public, protected или 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: значения этого класса только и доступны, когда доступ был предоставлен в форме наследования или их дочернего класса. обычно используется :: в предоставьте доступ родительскому классу

protected $familyWealth;


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

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

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

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

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

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

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

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

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


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

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

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


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

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

Public

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

защищенный

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

частная

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