Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

criatividade zero

[Resolvido] private não funciona

Recommended Posts

no exemplo abaixo eu consigo obter o valor de $foo-> testando

não deveria poder, ja que é private

algo de errado?

 

 

$_foo = new Foo;
$foo-> teste();
print_r( $foo-> testando );

class Foo
{
/*
**
*/
private $testando = array();
}


/*
**
*/
class Bar extends Foo
{
/*
**
*/
public function teste()
{
	/*
	**
	*/
	$this-> testando = 'opa';
}
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Teu Código está errado, deveria ser:

 

$foo = new Bar;
$foo->teste();
print_r( $foo->testando );

class Foo
{
       /*
       **
       */
       private $testando = array();
}


/*
**
*/
class Bar extends Foo
{
       /*
       **
       */
       public function teste()
       {
               /*
               **
               */
               $this->testando = 'opa';
       }
}

 

O PHP cria duas variáveis $testando uma é privada com valor = array () e uma outra que é pública com valor = opa.

Você pode verificar que se você alterar o código para esse abaixo, você não tem mais acesso a variável private criada na classe pai.

 

$foo = new Bar;
$foo->teste();
print_r( $foo->_testando );


class Foo
{
       /*
       **
       */
       private $_testando = array('privado');
}


/*
**
*/
class Bar extends Foo
{
       /*
       **
       */
       public function teste()
       {
               /*
               **
               */
               $this->_testando[] = 'opa';
       }
}

 

Se fosse a mesma variável, deveria resultar em:

Array ( [0] => privado [1] => opa )

e não:

Array ( [0] => opa )

 

Entendeu?

Compartilhar este post


Link para o post
Compartilhar em outros sites

... na verdade errei quando escrevi aqui

o correto é a instancia de bar

$_bar = new Bar;
$bar-> teste();
print_r( $bar-> testando );

 

 

private $_testando continua como private e sendo exibido

o exemplo que você deu apenas muda a saida pq você refez a array

 

 

se refizer sem extends, $_testando passa a nao ser acessado:

 

/*
**
*/
class Bar
{
       /*
       **
       */
       private $_testando = array('privado');

       /*
       **
       */
       public function teste()
       {
               /*
               **
               */
               $this->_testando[] = 'opa';
       }
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pois é, como você está na mesma classe, o PHP consegue validar a regra de visibilidade da variável. Como no caso inicial trata-se de uma classe extendida, o PHP não tem a visibilidade a variável da classe Pai, desta forma, o próprio PHP entende que você está setando uma variável nova quando você faz a declaração que a variável $_testando recebe um novo valor. Para evitar esses tipos de problemas, como boa regra na programação, vale a pena você criar protected métodos __set , __get e também criar um para mostrar a variável.

 

Exemplo:

 

$bar = new Bar;
$bar->teste();
echo '<br />';
$bar->mostrar_testando();

class Foo
{

       private $_testando = array('privado');
       protected function __set($name, $value) {
               echo "Setando '$name' para '$value'\n";
               $this->_testando[$name] = $value;
       }

       protected function __get($name) {
               echo "Obtendo '$name'\n";
               if (array_key_exists($name, $this->_testando)) {
                       return $this->_testando[$name];
               }
               $trace = debug_backtrace();
               trigger_error(
                   'Propriedade não definida via __get(): ' . $name .
                   ' em ' . $trace[0]['file'] .
                   ' na linha ' . $trace[0]['line'],
                   E_USER_NOTICE);
               return null;
       }
       public function mostrar_testando(){
               print_r( $this->_testando );
       }
}

class Bar extends Foo
{

       public function teste()
       {

               $this->_testando = 'opa';
       }
}

 

Acho que assim tudo funcionaria como o esperado. Me confirme se era isso que você queria.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você só consegue acessar um atributo private dentro da própria classe,impossível acessá-lo fora.

Dependendo do que queres fazer, faça enpasulamento deste atributo, e o chame de public, que então poderá chamá-lo em qualquer classe.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Provavelmente seus alertas de erro estão muito baixos ou desativados pois do jeito que você demonstrou no post #3 geraria o seguinte erro:

 

Notice: Undefined variable: bar...

E

Fatal error: Call to a member function teste() on a non-object...

E mesmo se consertasse trocando $_bar por $bar, teria esse outro:

 

Notice: Undefined property: Bar::$testando

E se consertasse trocando o testando por _testando, finalmente teria:

 

Fatal error: Cannot access private property Bar::$_testando...

Lembre-se de sempre que estiver desenvolvendo, iniciar o script com:

 

ini_set( 'display_errors', TRUE );

error_reporting( E_ALL | E_STRICT );

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que assim tudo funcionaria como o esperado. Me confirme se era isso que você queria.

na verdade não quero 'arrumar' outra forma de fazer, o problema é um atributo privado sendo acessado fora da classe

 

 

Bruno,

quando estou desenvolvendo defino o seguinte:

date_default_timezone_set ( 'America/Sao_Paulo' );
ini_set                   ( 'display_errors' , true );
error_reporting           ( E_ALL | E_STRICT );
ini_set                   ( 'default_charset', 'UTF-8' );

 

acontece que não ha alerta nenhum, de nenhum tipo

ignore o erro de digitação :)

o exemplo dando erro ainda, a saida é a seguinte:

 

$_bar = new Bar;

$_bar-> teste();

print_r( $_bar);

 

class Foo
{
       private $testando = array();
}


class Bar extends Foo
{
       public function teste()
       {
               $this-> testando = 'opa';
       }
}

Bar Object
(
   [testando:Foo:private] => Array
       (
       )

   [testando] => opa
)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você apenas está estranhando o retorno obtido, mas está certo.

 

Quando você declara:

 

class Foo {

   private $testando = array();
}

Você define explícitamente que todo e qualquer objeto de Foo poderá usar, dentro de seu contexto, a propriedade testando, que é um array.

 

Quando você faz:

 

class Bar extends Foo {

   public function teste() {

       $this -> testando = 'opa';
   }
}

Você define que quando Bar::teste() for invocado, a propriedade testando, visivelmente presente na classe-pai terá o valor opa.

 

Mas veja a visibilidade da propriedade testando. Ela é private, ou seja, de acessibilidade restrita única e exclusivamente no contexto de Foo. Bar JAMAIS terá acesso à ela.

 

Mas e por quê funciona?

 

Simples. Porque como você não definiu uma propriedade chamada testando em Bar e a existente em Foo é particular (já que privada é feio :P ), o interpretador precisa obedecer sua vontade com a string opa então ele cria uma propriedade em runtime.

 

E por omissão de visibilidade, public é internamente atribuído.

 

Mas não deveria haver um conflito de nomes?

 

Na minha opinião, isso deveria de fato acontecer, mas verdade não acontece. O motivo também é simples: hierarquia de visibilidade (inventei isso agora):

 

Nessa hierarquia tem-se:

 

|- private
 |- protected
   |- public

Isso significa que public é a visibilidade mais fraca de todas. Mas não se engane, aqui o jogo rola ao contrário. A visibilidade mais fraca supera a mais forte (private).

 

É a mesma coisa que um quatro de paus no Jogo de Truco. É a carta mais fraca do jogo, mas se vira o três, ela se transforma no todo poderoso gato (ou zap, se estiver em São Paulo).

 

Mas como assim?

 

Faça os testes e veja o interpretador reclamando:

 

  • Se você definir Foo::testando como public, nada vai mudar e $bar -> testando retornará opa
  • se você comentar Foo::testando, ainda verá opa, por causa da criação em runtime
  • Se você definir Foo::testando como public e criar um Bar::testando com qualquer visibilidade diferente de public verá:
     
    Fatal error: Access level to Bar::$testando must be public (as in class Foo)

Entendeu?

 

O código para funcionar de forma adequada e esperada deveria ter Foo::testando como protected e, se necessário, um Foo::getTestando(), para que você resgate o valor a nível de instância.

 

Por ser protected, quando Bar::teste() tenta modificar uma propriedade que ela desconhece, vai procurar na classe pai e por encontrar E puder enxergar, vai modificá-la sem criar outra em tempo de execução.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isso, isso, isso, isso, isso, isso, isso, isso... ^_^

 

Bem que seria interessante que ele mudassem isso. Tem muita coisa no PHP que é automatica que não deveria ser pra não acabar confundindo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

então se eu usar metodo publico a classe Bar vai poder usar a propriedade de Foo

não acho que seja necessário um getter para o propósito, é apenas um controle extends para eu poder acessar algumas propriedades diretamente na execução: executa, processa e acessa

 

 

concordo que deveria mudar isso :)

mas como nada é perfeito...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não, se você não precisa de um getter para que possa usar o valor fora da classe, isto é, a nível da instância, como ecoá-la, por exemplo, então protected resolve.

Compartilhar este post


Link para o post
Compartilhar em outros sites

E temos mais uma vez aqui ilustrado um dos aspectos meio incompreensíveis do PHP.

Eu já tinha observado o que o Bruno Augusto falou no post #8, mas não postei pois estou meio corrido aqui com o final do semestre na faculdade.

 

De fato, o PHP gosta de 'assumir' coisas. Se você tenta utilizar uma constante não definida, ele 'assume' que é uma string. Se você tenta acessar uma propriedade inexistente, ele tenta criá-la.

 

Quem sabe o PHP6 resolva essas questões, que acabam realmente confundindo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.