Qual a diferença entre público, privado e protegido?


989

Quando e por que eu deveria usar public, privatee protectedfunções e variáveis dentro de uma classe? Qual a diferença entre eles?

Exemplos:

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

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

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

59
Penso que esta pergunta também se beneficiaria de respostas com exemplos práticos do uso de cada um, em vez de fornecer a definição literal do que cada palavra-chave faz.
Matthew

70
Eu realmente acho que essa pergunta deve ser pública, não protegida.
dotancohen

Respostas:


1261

Você usa:

  • public escopo para disponibilizar essa propriedade / método de qualquer lugar, outras classes e instâncias do objeto.

  • private escopo quando você deseja que sua propriedade / método seja visível apenas em sua própria classe.

  • protected escopo quando você deseja tornar sua propriedade / método visível em todas as classes que estendem a classe atual, incluindo a classe pai.

Mais: (Para informações abrangentes)


79
protectedescopo quando você deseja tornar sua variável / função visível em todas as classes que estendem a classe atual E suas classes pai .
Shahid

4
@ Shahid - Eu não entendo o seu ponto. Qualquer classe que estende a classe A também estende a classe pai de A, não?
JDelage

4
@JDelage - Por favor, veja o linkhttp://www.php.net/manual/en/language.oop5.visibility.php#109324
Shahid

4
@ Growler Por que se preocupar em usar objetos então?
J.Steve

27
@ Growler, uma resposta mais útil seria que é bom esconder o máximo possível do funcionamento interno de um objeto. Dessa forma, é menos provável que quebre. Se você tornar tudo público, outro programador poderá alterar uma variável que você não deseja que seja alterada por nada além do funcionamento interno do seu objeto.
Relaxando em Chipre

1176

dd

Público:

Quando você declara um método (função) ou uma propriedade (variável) como public, esses métodos e propriedades podem ser acessados ​​por:

  • A mesma classe que o declarou.
  • As classes que herdam a classe declarada acima.
  • Quaisquer elementos estranhos fora desta classe também podem acessar essas coisas.

Exemplo:

<?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'

Protegido:

Quando você declara um método (função) ou uma propriedade (variável) como protected, esses métodos e propriedades podem ser acessados ​​por

  • A mesma classe que o declarou.
  • As classes que herdam a classe declarada acima.

Membros externos não podem acessar essas variáveis. "Estranhos" no sentido de que não são instâncias de objetos da própria classe declarada.

Exemplo:

<?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

O erro exato será este:

Erro fatal do PHP: Não é possível acessar a propriedade protegida GrandPa :: $ name


Privado:

Quando você declara um método (função) ou uma propriedade (variável) como private, esses métodos e propriedades podem ser acessados ​​por:

  • A mesma classe que o declarou.

Membros externos não podem acessar essas variáveis. Pessoas de fora no sentido de que não são instâncias de objetos da própria classe declarada e nem mesmo as classes que herdam a classe declarada.

Exemplo:

<?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

As mensagens de erro exatas serão:

Aviso: Propriedade indefinida: Papai :: $ name
Erro fatal: Não é possível acessar a propriedade privada GrandPa :: $ name


Dissecando a Classe Vovô Usando Reflexão

Esse assunto não está realmente fora do escopo, e estou adicionando aqui apenas para provar que a reflexão é realmente poderosa. Como afirmei nos três exemplos acima, protectede os privatemembros (propriedades e métodos) não podem ser acessados ​​fora da classe.

No entanto, com a reflexão, você pode fazer o extraordinário , mesmo acessando protectede privatemembros fora da classe!

Bem, o que é reflexão?

O Reflection adiciona a capacidade de fazer engenharia reversa de classes, interfaces, funções, métodos e extensões. Além disso, eles oferecem maneiras de recuperar comentários de documentos para funções, classes e métodos.

Preâmbulo

Temos uma classe nomeada Grandpase dizemos que temos três propriedades. Para facilitar o entendimento, considere que existem três vovôs com nomes:

  • Mark Henry
  • John Clash
  • Will Jones

Vamos torná-los (modificadores atribuir) public, protectede privaterespectivamente. Você sabe muito bem que protectede privatemembros não pode ser acessado fora da classe. Agora vamos contradizer a afirmação usando reflexão.

O código

<?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>";
}

Resultado:

#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

Equívocos comuns:

Por favor, não confunda com o exemplo abaixo. Como você ainda pode ver, os membros privatee protectednão podem ser acessados fora da classe sem usar a reflexão

<?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);

Resultado:

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

Funções de depuração

print_r, var_exportE var_dumpsão funções do depurador . Eles apresentam informações sobre uma variável em uma forma legível por humanos. Essas três funções revelarão as propriedades protectede privatedos objetos no PHP 5. Membros da classe estática não serão mostrados.


Mais recursos:



desculpas pelo atraso adicionam-se a este convo. Você pode me dizer por que alguém usaria isso? Você explicou perfeitamente como eles funcionam etc. Gostaria de saber os benefícios do uso de cada um deles. Obrigado
JamesG

@JamesG é um pouco explicado no outro comentário acima. stackoverflow.com/questions/4361553/…
cjmling 5/17

Não sei por que talvez esteja um pouco fora dessa questão, mas ninguém mencionou que no PHP existem outros dois modificadores de acesso: abstract e final essa palavra-chave pode ser usada apenas para classes PHP, mas ainda acessa modificadores
bxN5

1
Eu sugiro que você leia a explicação sobre abstração fornecida por Dhairya Lakhera aqui: stackoverflow.com/questions/2558559/… . É um complemento perfeito para as explicações de Shankar Damodaran.
Julio Marchi

83

Geralmente, é considerado uma boa prática padronizar a visibilidade mais baixa necessária, pois isso promove o encapsulamento de dados e o bom design da interface. Ao considerar a visibilidade da variável e do método, pense no papel que o membro desempenha na interação com outros objetos.

Se você "codifica para uma interface ao invés de implementação", geralmente é bastante simples tomar decisões de visibilidade. Em geral, as variáveis ​​devem ser privadas ou protegidas, a menos que você tenha um bom motivo para expô-las. Use acessadores públicos (getters / setters) em vez de limitar e regular o acesso aos internos de uma classe.

Para usar um carro como analogia, coisas como velocidade, marcha e direção seriam variáveis ​​de instância privadas. Você não quer que o motorista manipule diretamente coisas como proporção ar / combustível. Em vez disso, você expõe um número limitado de ações como métodos públicos. A interface para um carro pode incluir métodos, tais como accelerate(), deccelerate()/ brake(), setGear(), turnLeft(), turnRight(), etc.

O motorista não sabe nem deve se preocupar em como essas ações são implementadas pelos internos do carro, e expor essa funcionalidade pode ser perigoso para o motorista e outras pessoas na estrada. Daí a boa prática de projetar uma interface pública e encapsular os dados por trás dessa interface.

Essa abordagem também permite alterar e melhorar a implementação dos métodos públicos em sua classe sem violar o contrato da interface com o código do cliente. Por exemplo, você poderia melhorar o accelerate()método para economizar mais combustível, mas o uso desse método permaneceria o mesmo; o código do cliente não exigiria alterações, mas ainda colherá os benefícios de sua melhoria de eficiência.

Edit: Uma vez que parece que você ainda está no meio de aprendizagem de conceitos orientados a objetos (que são muito mais difíceis de dominar do que a sintaxe de qualquer idioma), eu altamente recomendo pegar uma cópia de objetos PHP, padrões e prática por Matt Zandstra. Este é o livro que primeiro me ensinou como usar OOP efetivamente, ao invés de apenas me ensinando a sintaxe. Eu havia aprendido a sintaxe anos antes, mas isso era inútil sem entender o "porquê" do OOP.


3
O livro recomendado na edição deste post é realmente muito excelente. O pedaço que eu até agora se mostrou bastante esclarecedor. Os primeiros capítulos responderam à maioria das minhas perguntas relacionadas à classe.
Josiah

Os livros que me permitiram realmente entender objetos, sem ocultar meu pensamento com detalhes desnecessários, como exemplos em Smalltalk, foram de David A Taylor, sendo Tecnologia Orientada a Objetos: Guia de um Gerente e Engenharia de Negócios com Teecologia de Objetos . Ambos são apenas 100 páginas e cada um é fácil de ler em uma tarde. Obviamente, existem os Padrões de Design de Gamma e cols. , Embora a abordagem básica possa ser simplesmente descrita por 'subclasse que você deseja variar'.
Patânjali

Uma analogia muito boa. Você tem um para protegido x privado?
21918 Jänis Elmeris

79

private - pode ser acessado somente dentro da classe

protected - pode ser acessado de DENTRO da classe e das classes INHERITING

public - também pode ser acessado a partir do código FORA da classe

Isso se aplica a funções e variáveis.


Não tenho certeza se a definição protegida está correta aqui, a partir da resposta selecionada real parece, Protected - Pode ser acessado apenas a partir da classe herdada e não da classe original / pai. Dizer "DENTRO da turma" pode ser um pouco confuso.
pal4life

7
Acho que não, de fato, parece que a resposta selecionada é a que está confusa aqui. Veja o comentário de Shahids. IMHO, um método protegido pode muito bem ser acessado de dentro da classe original.
Olaf

uma classe pode acessar o público de outra classe?
Serjas

1
@ Serjas: Não, apenas outro objeto, a menos que sejam métodos / campos estáticos.
DanMan

Não sei se isso se aplica a todas as linguagens de programação, mas no PHP as propriedades / métodos "protegidos" podem ser acessados ​​na classe em que foi declarado ou nas classes que herdam da classe que define a propriedade / método.
John Slegers 19/03/2015

25

A diferença é a seguinte:

Public :: Uma variável ou método público pode ser acessado diretamente por qualquer usuário da classe.

Protected :: Uma variável ou método protegido não pode ser acessado pelos usuários da classe, mas pode ser acessado dentro de uma subclasse que herda da classe.

Private :: Uma variável ou método privado só pode ser acessado internamente a partir da classe em que está definido. Isso significa que uma variável ou método privado não pode ser chamado de um filho que estende a classe.


17

Escopos de visibilidade com exemplos abstratos :: facilita a compreensão

Essa visibilidade de uma propriedade ou método é definida pré-fixando a declaração de uma das três palavras-chave (pública, protegida e privada)

Público : se uma propriedade ou método é definido como público, significa que pode ser acessado e manipulado por qualquer coisa que possa se referir ao objeto.

  • Resumo por exemplo. Pense no escopo da visibilidade pública como um "piquenique público" ao qual qualquer pessoa possa comparecer.

Protegido: quando uma visibilidade de propriedade ou método é definida como membros protegidos, o acesso só é possível dentro da própria classe e por classes herdadas e herdadas. (Herdado: - uma classe pode ter todas as propriedades e métodos de outra classe).

  • Pense como um escopo de visibilidade protegido como "piquenique da empresa", em que membros da empresa e familiares não são permitidos ao público. É a restrição de escopo mais comum.

Privado: quando uma visibilidade de propriedade ou método é definida como privada, somente a classe que possui membros privados pode acessar esses métodos e propriedades (internamente na classe), apesar de qualquer relação de classe que possa existir.

  • com analogia ao piquenique, pense como um "piquenique da empresa onde apenas os membros da empresa são permitidos" no piquenique. nem família nem público em geral são permitidos.

15
/**
 * 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

Extraído de :

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


12

⚡️ Aqui está uma maneira fácil de lembrar o escopo de public, protectede private.

PUBLIC:

  • public escopo: uma variável / função pública está disponível para objetos e outras classes.

PROTECTED:

  • protected escopo: uma variável / função protegida está disponível para todas as classes que estendem a classe atual.
  • Não! Objetos não podem acessar este escopo

PRIVATE:

  • private escopo: Uma variável / função privada é visível apenas na classe atual em que está sendo definida.
  • Não! A classe que estende a classe atual não pode acessar esse escopo.
  • Não! Objetos não podem acessar esse escopo.

Leia a Visibilidade de um método ou variável no Manual do PHP.


9

Considerando ' quando ':
tenho a tendência de declarar tudo como privado inicialmente, se não tiver exatamente certeza. Por isso, geralmente é muito mais fácil tornar público um método privado do que o contrário. Isso porque você pode pelo menos ter certeza de que o método privado não foi usado em nenhum outro lugar, exceto na própria classe. Um método público já pode estar em uso em qualquer lugar, possivelmente exigindo uma extensa reescrita.

Atualização : eu uso o padrão protectedhoje em dia, porque descobri que é bom o suficiente para encapsulamento e não atrapalha quando estou estendendo as classes (o que tento evitar mesmo assim). Somente se eu tiver um bom motivo para usar os outros dois, eu o usarei.

Uma boa razão para um privatemétodo seria aquela que implementa algo inerente a esse objeto que mesmo uma classe estendida não deve mudar (razão de fato, além do encapsulamento, como gerenciamento interno do estado). Eventualmente, ainda é fácil o suficiente rastrear onde um protectedmétodo está sendo usado normalmente, então eu uso o padrão protectedatualmente. Talvez não seja uma experiência 100% objetiva "nas trincheiras", admito.


3
Com a sua atualização: você pode deixar mais claro como "bom o suficiente" e "bom motivo" caminham juntos aqui? Por exemplo, o uso privateainda seria "bom o suficiente" para ser usado, mas você não sugere mais que, embora os motivos anteriores, você tenha soado como um "bom motivo" ainda: encapsulamento.
hakre

@hakre: A razão pela qual devemos lutar pelo encapsulamento é evitar o vazamento do estado para o escopo externo. protectedjá faz isso, mas você o mantém flexível para extensão / herança. Novamente, a menos que você tenha um bom motivo para fazê-lo private.
21417 DanMan

Bem, esse é provavelmente o ponto em que discordamos: protectedna verdade, vaza para o escopo externo e geralmente está no seu caminho, pois suporta decisões de design ruins, como favorecer implicitamente a herança enquanto é melhor favorecer a composição. É por isso que seguir com o privado, a menos que você tenha requisitos reais, geralmente é a melhor maneira de começar a escrever código. Isso também impedirá a tomada de decisões de design muito cedo, enquanto elas ainda não são necessárias.
hakre

Não discutirei com o seu argumento geral, porque é justo o suficiente, mas protectednão vaza para o escopo externo (código que está chamando / acessando o método / campo), mas apenas para o escopo interno (estendendo classes). Há uma diferença, por menor que seja para você. É muito mais fácil rastrear o uso de um protectedcampo do que publicum.
DanMan

6

O manual do PHP tem uma boa leitura sobre a questão aqui .

A visibilidade de uma propriedade ou método pode ser definida prefixando a declaração com as palavras-chave public, protected ou private. Os membros da classe declarados públicos podem ser acessados ​​em qualquer lugar. Os membros declarados protegidos podem ser acessados ​​apenas dentro da própria classe e pelas classes herdada e pai. Os membros declarados como privados podem ser acessados ​​apenas pela classe que define o membro.


6

Para mim, esta é a maneira mais útil de entender os três tipos de propriedades:

Público : use isso quando estiver OK, com esta variável sendo acessada diretamente e alterada de qualquer lugar no seu código.

Exemplo de uso de fora da classe:

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

Protegido : use isso quando desejar forçar outros programadores (e você mesmo) a usar getters / setters fora da classe ao acessar e definir variáveis ​​(mas você deve ser consistente e usar os getters e setters dentro da classe). Essa ou privatetende a ser a maneira padrão em que você deve configurar todas as propriedades da classe.

Por quê? Como se você decidir, em algum momento no futuro (talvez até 5 minutos), que deseja manipular o valor retornado para essa propriedade ou fazer algo com ela antes de obter / configurar, poderá fazer isso sem refatorar em qualquer lugar que tenha usou no seu projeto.

Exemplo de uso de fora da classe:

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

Privado : as privatepropriedades são muito semelhantes às protectedpropriedades. Mas a característica / diferença distintiva é que torná- privatelo inacessível às classes filho sem usar o getter ou setter da classe pai.

Então, basicamente, se você estiver usando getters e setters para uma propriedade (ou se ela for usada apenas internamente pela classe pai e não for acessível em qualquer outro lugar), você poderá fazê-lo private, apenas para impedir que alguém tente para usá-lo diretamente e introduzir bugs .

Exemplo de uso dentro de uma classe filho (que estende MyObject):

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


4

Variáveis ​​no PHP são convertidas em três tipos diferentes:

Público: os valores desses tipos de variáveis ​​estão disponíveis em todo o escopo e exigem a execução do seu código. declarar como:public $examTimeTable;

Privado: os valores desse tipo de variável estão disponíveis apenas para a classe a que pertencem. private $classRoomComputers;

Protegido: valores desta classe apenas e disponíveis apenas quando o Access foi concedido em uma forma de herança ou em sua classe filho. geralmente usado ::para conceder acesso pela classe pai

protected $familyWealth;


3

Revivendo uma pergunta antiga, mas acho que uma maneira realmente boa de pensar nisso é em termos da API que você está definindo.

  • public - Tudo o que é marcado como público faz parte da API na qual qualquer pessoa que use sua classe / interface / outra irá usar e confiar.

  • protected- Não se engane, isso também faz parte da API! As pessoas podem criar subclasses, estender seu código e usar qualquer coisa marcada como protegida.

  • private- Propriedades e métodos privados podem ser alterados quanto você quiser. Ninguém mais pode usar isso. Essas são as únicas coisas que você pode alterar sem fazer alterações.

Ou, em termos de Semver :

  • Alterações em qualquer coisa publicou protecteddevem ser consideradas alterações PRINCIPAIS.

  • Qualquer coisa nova publicou protecteddeve ser (pelo menos) MENOR

  • Somente novas / alterações em qualquer coisa privatepodem ser PATCH

Portanto, em termos de manutenção de código, é bom ter cuidado com o que você faz publicou protectedporque essas são as coisas que você promete aos seus usuários.


1

Quando seguimos o php orientado a objetos em nosso projeto, devemos seguir algumas regras para usar modificadores de acesso no php. Hoje vamos aprender claramente o que é modificador de acesso e como podemos usá-lo. Os modificadores de acesso PHP são usados ​​para definir direitos de acesso com classes PHP e seus membros, que são as funções e variáveis ​​definidas no escopo da classe. No php, existem três escopos para os alunos.

  1. PÚBLICO
  2. PRIVADO
  3. PROTEGIDO

Agora, vamos dar uma olhada na imagem a seguir para entender o nível de acesso do modificador de acesso insira a descrição da imagem aqui

Agora, vamos dar uma olhada na lista a seguir para saber sobre as possíveis palavras-chave PHP usadas como modificadores de acesso.

public: - a classe ou seus membros definidos com este modificador de acesso estarão acessíveis ao público de qualquer lugar, mesmo fora do escopo da classe.

private: - membros da classe com esta palavra-chave serão acessados ​​dentro da própria classe. não podemos acessar dados privados da subclasse. Ele protege os membros do acesso à classe externa.

protected: - o mesmo que private, exceto permitindo que as subclasses acessem membros da superclasse protegida.

Agora veja a tabela para entender o modificador de acesso Leia o artigo completo php access modifire


1

Public: é um estado padrão quando você declara uma variável ou método, pode ser acessado por qualquer coisa diretamente no objeto.

Protected: Pode ser acessado apenas dentro do objeto e subclasses.

Private: Pode ser referenciado apenas dentro do objeto, não subclasses.


0

As palavras-chave mencionadas são modificadores de acesso e nos ajudam a implementar o encapsulamento (ou ocultação de informações). Eles informam ao compilador quais outras classes devem ter acesso ao campo ou método que está sendo definido.

privado - Somente a classe atual terá acesso ao campo ou método.

protected - Somente a classe e subclasses atuais (e às vezes também as classes do mesmo pacote) dessa classe terão acesso ao campo ou método.

public - Qualquer classe pode se referir ao campo ou chamar o método

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.