0

Extendendo dinamicamente uma classe

criado por David Bittencourt em 14/11/2003 10:19am
A maneira usual de extender uma classe é a seguinte:

<?php

class foo {

    var $value=1;
    function show(){
        echo $this->value;
   }

}

class bar extends foo {

    var $value_bar;
    function show_bar(){
        $this->value++;
        $this->show();
    }

}

?>

Neste caso, classe "bar" extende a classe "foo" com a nova função "show_bar()" e a variável $value_bar. Uma maneira de usar este código é:

<?php

$foo = new foo;
$foo->show(); // retorna 1

$bar = new bar;
$bar->show_bar(); // retorna 2

// note que

$foo = new foo;
$foo->show_bar(); // retorna erro

?>

O problema está no seguinte caso:

"Quero construir uma classe com algumas funções básicas e várias funções extras que podem (ou não) ser necessárias, separadamente e em qualquer ordem, ao utilizar a classe e somente nela."

Vejamos uma solução incorreta.

Comentários:

Mostrando 1 - 10 de 13 comentários
Olá, DAVI:

O JavaScript abaixo não roda através do navegador Firefox. Será que VC poderia me ajudar alterando algum(s) parâmetro(s) ? Agradeço desde já = Fiumari:
<script language="JavaScript"> var ultimo=-1, dBanner;
function carrega(x) {dBanner=x;Banners()}
function Banners()
{ var MNews = new Array();
MNews[0]= '<iframe " name="_blank" scrolling="no" src="http://www.finet.com.br/google.htm" width="100%" frameborder="0" target="_blank" height="350" BORDER="0"></iframe><a href="http://www.finet.com.br/google.htm" target="_blank"></a>';
MNews[1]= '<iframe " name="_blank" scrolling="no" src="http://www.finet.com.br/google2.htm" width="100%" frameborder="0" target="_blank" height="350" BORDER="0"></iframe><a href="http://www.finet.com.br/google2.htm" target="_blank"></a>'
while((Numero = parseInt(Math.random()*MNews.length))==ultimo);
dBanner.innerHTML=MNews[Numero];
setTimeout("Banners()",15000);
} </script>
03/09/2007 11:09am (~9 anos atrás)

Realmente Hugo isto acontece. Percebi outro dia no meu projeto. Uma forma de corrigir isso aí é copiando todas as variáveis da classe na nova extendida:

<?php

// Função "extend" da classe "foo"
function extend($codigo) {

$nome_classe = get_class($this);

srand((double)microtime()*1000000);
$nome_nova_classe = $nome_classe . rand(0,99);

eval('class '. $nome_nova_classe .' extends '. $nome_classe .' { '. $codigo .' }');

$obj = new $nome_nova_classe();

$vars = get_class_vars($nome_classe);
foreach($vars AS $key=>$value) {
$obj->$key = &$this->$key;
}

$this = $obj;
unset($obj);

}
?>
14/12/2003 2:06pm (~13 anos atrás)

Hugo P.L. disse:
Qdo vc carregar o plugin vc vai perder todos os atributos da classe não? sendo obrigado a carregar o plugin antes de mecher em qualquer coisa da classe....
14/12/2003 1:17pm (~13 anos atrás)

Muito bem lembrado Eduardo. Nem tinha me tocado disso.

Uma maneira de corrigir isso é substituir a linha da função 'extend':

$nome_nova_classe = $nome_classe . "_ext";

por:

srand((double)microtime()*1000000);
$nome_nova_classe = $nome_classe . rand(0,999);

A probabilidade de redeclarar uma classe cai bastante usando esse código.
21/11/2003 2:00pm (~13 anos atrás)

Eduardo Dias disse:
Ocorre um problema junto ao codigo explicado: quando eu tenho diversos objetos que de uma mesma classe e crio dinamicamente esta extensão ele emitira um erro dizendo que no pode redeclarar a classe, sendo necessario ( julgo melhor ).. alterar em vez de *_ext ser *_(nome do objeto )...


Abraços
21/11/2003 1:04pm (~13 anos atrás)

explicou direitinho sim.. entendi
fica bem dinâmico e interessante de se trabalhar deste jeito que você falou

tem algum grande projeto que você desenvolveu baseando-se neste esquema proposto no artigo ?
18/11/2003 11:47am (~13 anos atrás)

Olha, no fundo é isso que a função 'extend' está fazendo usando eval(). Vou tentar explicar a vantagem.

Do jeito que você está falando, para usar a função 'foo_foo_foo', você tem que criar um objeto assim:

<?php
$myfoo = new myfoo;
?>

O jeito que eu estou propondo é concentar tudo na classe base (ou "brain" como você chamou =) ).

<?php
$foo = new foo;
$foo->plugin('myfoo');
$foo->foo_foo_foo();
?>

Aqui não vemos muitas vantagens, mas se tivermos mais plugins? Do jeito que você está falando:

<?php
$myfoo = new myfoo;
$yourfoo = new yourfoo;
$ourfoo = new ourfoo;
// ...
?>

Ou seja, preciso ter diversos objetos individuais para cada plugin.

Se usar a função 'plugin':

<?php
$foo = new foo; // base
$foo->plugin('myfoo');
$foo->plugin('yourfoo');
$foo->plugin('ourfoo');
?>

Você tem disponível todas os plugins no mesmo objeto $foo. Não é legal? =)

Realmente eu sei que o PEAR, e outras clases funcionam deste jeito que você falou. Mas num projeto recente eu vi vantagem de usar tal método.

A explicação que eu vejo para o PEAR usar desta maneira é que as classes que extendem a base PEAR são grandes e completas, com grande número de funções. Assim, você utilizará somente a nova classe que extende PEAR.

Em se tratando de um grande número de funções extras que você queira incorporar, onde em um script você precisa somente de certo plugin e em outro um plugin diferente, chamar dinamicamente tais funções, individualmente, é, ao meu ver, uma vantagem.

Neste caso seriam diversas funções que tem propósitos diferentes e que não tem relação umas com as outras, não havendo vantagem em juntar em uma classe única que extende a base.

Espero que tenha explicado meu ponto de vista. =)

Um abraço!
18/11/2003 10:37am (~13 anos atrás)

cara, seu artigo é muito legal, só que

eu estava vendo o padrão da pear e algumas classes que estou usando, e reparei o seguinte:

há um arquivo PEAR.php com a classe
e como você disse para não "sujar" muito a classe com coisas desnecessarias cria-se o "brain" do negocio que fica nesse arquivo ai..

e um novo codigo é feito num outro arquivo php

foo.php

com uma classe
<?php
class myfoo extends PEAR {
function foo_foo_foo
}

?>

dai você trabalha chamando o PEAR.php

e eventualmente os teus packages né..
tuas subclasses, teus features sei lá.. nomeação é o que não falta..

mas seria uma outra forma de estar trabalhando não ?

bom, é isso!

Abraços!
17/11/2003 7:22pm (~13 anos atrás)

Bom, se você não entende porque nao vê vantagens veja um outro artigo (hehe, sem propagandas) do André de Castro Zorzo que fala sobre classes no PHP também.

Espero ter ajudado
17/11/2003 7:16pm (~13 anos atrás)

Newton Wagner disse:
Valeu ae.. eu não aprendo muito bem as classes por que não consigo enxergar realmente a vantagem de utilizá-las. :).

Vou ver se dou uma lida sobre isso por aí! Valeu a ajuda!
17/11/2003 6:37am (~13 anos atrás)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)