Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Pessoal eu estava fazendo um estudo dirigido sobre classes static e cheguei a seguinte conclusão:
>
static $quantidade=0;// Cria-se uma variavel chamada quantidade cujo valor inicial é igual a 0, ela tem o atributo chamado static que é:
/*
Este atributo diz a variavel que ela é uma variavel estatica, ou seja, é o mesmo valor compartilhado por todas as classes,Exemplo pratico:
Em um variavel do tipo public chamada nome (public $nome;) nos nao podemos realizar este tipo de comando:
new Carrinho('Geladeira111');
new Carrinho('Geladeira'678);
new Carrinho('Geladeira455');
pois a variavel so pode assumir uma forma, ja quando a variavel é do tipo static podemos realizar isso, pois é como se ela se duplicasse ou seja acada instancia new passando valores é como se o php criasse outra copia dessa classe com o mesmo nome, ou seja:
static $quantidade = "geladeira111";
static $quantidade = "geladeira678";
static $quantidade = "geladeira455";
Os valores das classes do tipo estatica so podem ser setados atraves do self:: + variavel, elas nao podem ser setadas atravez do comando $this->quantida = +variavel
Estou certo? se estiver errado me corrijam?
Não aprofundando muito, mas:
<?php
Class Carrinho
{
static $quantidade =0;
public function __construct($qtd){
// $this->quantidade = $qtd; // Erro -> conteudo estatico não é acessivel pelo $this
self::$quantidade = $qtd; // Correto
}
static public function getQtd(){
return self::$quantidade;
}
}
$carrinho = new Carrinho(5);echo Carrinho::getQtd();
Carrinho::$quantidade = 5;
echo Carrinho::getQtd();Calma rsrs ainda sou iniciante em orientação a objetos vamos la a primeira coisa que digo é que segui esta linhas de raciocinio observe:
Public -> Todos as variaveis ou funções que virem com este metodo podem ser acessados tanto de dentro como de fora da classe exemplo:
Banheiros quimicos, calçadas, protitutas sao publicas e podem ser ultilizados tanto pelo governo como o povo
Falar, olhar, correr é publico pois todos nos temos estas caracteristicas
Private -> sao exclusivamente da classe e nao podem ser herdadas, exemplo:
Gosto (musical,alimento, etc..) nao se descute assim como as caracteristicas de uma pessoa, ela nao podem ser herdadas pois nen sempre um pai que gosta de rock o filho gostará de rock.O pai que seja super engraçado o filho sera, o pai tem conhecimento de fisica e quando o beber nascer ja sabendo fisica...
Protected -> so podem ser acessadas dentro da classe e podem ser herdadas, Exemplo:
A cor dos olhos, da pele entre outras caracteristicas geneticas, Fortuna... podem ser herdadas e usada pelos membros da familia, mas outra pessoa que nao seje da familia nao tem acesso a esse tipo de coisa.
Static -> não pode acessar qualquer outro atributo ou método da classe que também não seja estático. A vantagem é que se não se precisa instanciar um objeto para acessar-los. Exemplo:
OK, ate agora nao consegui usar um exemplo pratico para facil entendimento....
Imagine uma classe que valide coisas, retorna true caso seja válido e falso caso não:
class Valida{
static public function email(){
}
static public function cpf(){
}
}
com a classe estatica basta fazer isso:
$email = "email@host.com";
$eValido=Valida::email($email);
Se a classe não fosse estática precisaríamos instanciar um objeto Valida, o que consumiria mais recursos e daria um código mais longo e menos legível.
exe.:
$validador=new Valida();
$email = "email@host.com";
$eValido=$validador->email($email);
Existem outras possibilidades interessantes, como usar métodos estáticos para instanciar outros objetos, com isso podemos deixar programado a variáveis com que eles serão construídos pelo método estático. Depois para instancia-los bastaria um "getInstance()".
Métodos estáticos são muito importantes também para o padrão Registry, que funciona como um "quadro negro" quase como uma global onde a informações são registradas e são acessíveis a qualquer parte da aplicação.
Então, recomendo três discussões sobre OO aqui do forum mesmo:
http://forum.imasters.com.br/topic/505274-orientao-a-objetos-perguntas-e-respostas/
http://forum.imasters.com.br/topic/509413-interface-poo/
http://forum.imasters.com.br/topic/509651-classe-crud-com-pdo/
aaaah agora com esse exmplos entendi entao vamos lá:
Quando definimos uma função ou variavel do tipo public,protected ou private para acessar estas variaveis ou funções é necessario instanciar a classe ou seja:
new Valida(); // Inicia a classe que sera executada , funciona como um power on de um computador ou uma ignição de um carro.
Ja quando funções ou variaveis sao do tipo static nao é necessario mais iniciar a classe, é simplismente adicionar o nome da classe e fazer uma referencia :: + variavel ou função, exemplo:
Valida::email($email);
Mas ai tem contradições, pois sera que o comando:
Valida::email($email);
Nao seria a mesma coisa que esse:
$validador=new Valida();
$eValido=$validador->email($email);
So que de uma forma mais simplificada? Ou seja, para o programador pareçe ser simplificada mas pro PHP é a mesma coisa nao (PHP executa os mesmos procedimentos tanto no simplificado quando no normal)?
(PHP executa os mesmos procedimentos tanto no simplificado quando no normal)?
Se não há instancia, o interpretador não vai alocar memoria para tal.
Se não há instancia, o interpretador não vai alocar memoria para tal.
De acordo com meu exemplo:
new Valida(); // Inicia a classe que sera executada , funciona como um power on de um computador ou uma ignição de um carro.
então voce esta querendo dizer que é a mesma coisa do que eu andar com um carro ou executar um game no pc, mesmo nao tendo liga-o ou feito a ignição?
A questão esta no processo, em um site grande por exemplo você pode precisar validar milhares de emails, se este método não for estático pode ser preciso instanciar esses milhares de objetos em diferentes partes do sistema. cada um deles consumindo memoria e deixando o servidor mais lento. Com método estático você não precisa se preocupar com coisas como o tempo de vida dos hipotéticos objetos Valida e a memoria que eles estão consumindo, existe apenas uma classe lidando com o problema no sistema e não diversos objetos diferentes.
Em orientação a objetos, estáticos têm duas funções: criar objetos e ter estado global (evil evil evil). Em linguagens que não contêm suporte para funções, como Java, eles também são usados para fazer pure functions (funções sem efeitos colaterais e sem estado, apenas com input => output).
- Criação de objetos:
Vamos supor que nós temos um componente para fazer comparações matemáticas (>, <, >=, etc.).
interface Operator
{
public function matches($x, $y);
}
class GreaterThan implements Operator
{
public function matches($x, $y)
{
return $x > $y;
}
}
class LessThan implements Operator
{
public function matches($x, $y)
{
return $x < $y;
}
}
class Comparison
{
private $operator;
private $x;
private $y;
public function __construct(Operator $operator, $x, $y)
{
$this->operator = $operator;
$this->x = $x;
$this->y = $y;
}
public function matches()
{
return $this->operator->matches($this->x, $this->y);
}
}$comparison1 = new Comparison(new GreaterThan(), 5, 10);
$comparison1->matches(); // false
$comparison2 = new Comparison(new LessThan(), 5, 10);
$comparison2->matches(); // true
Para isso, poderíamos criar métodos estáticos na nossa classe Comparison para facilitar a criação:
public static function greaterThan($x, $y)
{
return new self(new GreaterThan(), $x, $y);
}
public static function lessThan($x, $y) return new self(new LessThan(), $x, $y);
}$comparison1 = Comparison::greaterThan(5, 10);
$comparison1->matches(); // false
$comparison2 = Comparison::lessThan(5, 10);
$comparison2->matches(); // true
Esse tipo de técnica é conhecida como "Static Factory". Não digo que seja bom ou ruim, depende muito do caso e deve-se tomar cuidado com o Open/Closed Principle.
- Estado global:
Durante muito tempo isso foi muito aplicado e falado (positivamente) na comunidade PHP, mas atualmente, com o começo da maturidade da linguagem e do ecossistema, hoje isso é evitado. Porém, vamos ver de qualquer forma.
Antes de tudo, é necessário compreender o estado em OOP, que é armazenado nas propriedades:
class Rectangle
{
public $height = 0;
public $weight = 0;
}
$rectangle1 = new Rectangle();
var_dump($rectangle1->height); // 0
var_dump($rectangle1->weight); // 0
$rectangle1->height = 5.75;
$rectangle1->weight = 9.40;
var_dump($rectangle1->height); // 5.75
var_dump($rectangle1->weight); // 9.40
Os objetos têm estado independente, ou seja, se eu mudar o estado de algum objeto, ele não muda o do outro:
$rectangle1 = new Rectangle();
$rectangle1->height = 5.75;
$rectangle1->weight = 9.40;
$rectangle2 = new Rectangle();
$rectangle2->height = 2.15;
$rectangle2->weight = 2.80;
var_dump($rectangle1->height); // 5.75
var_dump($rectangle1->weight); // 9.40
var_dump($rectangle2->height); // 2.15
var_dump($rectangle2->weight); // 2.80
No caso de estáticos, o estado é da classe e não do objeto, até porque não há um objeto (instância):
class StaticRectangle
{
public static $height = 0;
public static $weight = 0;
}
StaticRectangle::$height = 5.75;
StaticRectangle::$weight = 9.40;
StaticRectangle::$height = 2.15;
StaticRectangle::$weight = 2.80;
var_dump(StaticRectangle::$height); // 2.15
var_dump(StaticRectangle::$weight); // 2.80
No caso acima, não temos um objeto e acessamos a classe diretamente. Se eu mudo o estado, eu mudo globalmente e não somente no objeto.
Na prática, isso é usado para manter um estado de algo, como um banco de dados, logger, sistema de cache e afins, surgindo dois padrões: Singleton e Registry. Contudo, evite fazer isso, não é uma boa prática.
- Pure functions:
Elas não são nada mais do que funções que recebem alguns parâmetros e retornam algum valor, sem nenhum efeito colateral, sem acessar estado externo.
Na maioria das linguagens, é possível criar funções, mas em algumas não é porque elas obrigam você a trabalhar com classes. Em PHP, costuma-se fazer pure functions com métodos estáticos porque não existe autoloading para funções.
class Inflector
{
public static function camelCase($string)
{
return lcfirst(self::studlyCaps($string));
}
public static function studlyCaps($string)
{
return str_replace(
' ',
'',
ucwords(str_replace(['-', '_'], ' ', $string))
);
}
}
echo Inflector::camelCase('Alguma frase grande'); // algumaFraseGrande
echo Inflector::studlyCaps('Alguma frase estranha'); // AlgumaFraseEstranha
Mas nada nos impediria de fazer isso de forma orientada a objetos:
class Inflector
{
private $string;
public function __construct($string)
{
$this->string = $string;
}
public function camelCase()
{
return lcfirst($this->studlyCaps());
}
public function studlyCaps()
{
return str_replace(
' ',
'',
ucwords(str_replace(['-', '_'], ' ', $this->string))
);
}
}
echo (new Inflector('Alguma frase grande'))->camelCase(); // algumaFraseGrande
echo (new Inflector('Alguma frase estranha'))->studlyCaps(); // AlgumaFraseEstranha> Teoricamente de dentro dos escopo da classe o correto é usar self::$variavel ou self::funcao mas acredito que o $this-> funcione da mesma maneira.
Para acessar métodos e propriedades estáticas, usa-se self:: ou static::, $this-> é apenas para não-estáticos. Se rodar em E_STRICT dará erro.
>
Public -> Todos as variaveis ou funções que virem com este metodo podem ser acessados tanto de dentro como de fora da classe exemplo:
Banheiros quimicos, calçadas, protitutas sao publicas e podem ser ultilizados tanto pelo governo como o povo
Falar, olhar, correr é publico pois todos nos temos estas caracteristicas
Private -> sao exclusivamente da classe e nao podem ser herdadas, exemplo:
Gosto (musical,alimento, etc..) nao se descute assim como as caracteristicas de uma pessoa, ela nao podem ser herdadas pois nen sempre um pai que gosta de rock o filho gostará de rock.O pai que seja super engraçado o filho sera, o pai tem conhecimento de fisica e quando o beber nascer ja sabendo fisica...
Protected -> so podem ser acessadas dentro da classe e podem ser herdadas, Exemplo:
A cor dos olhos, da pele entre outras caracteristicas geneticas, Fortuna... podem ser herdadas e usada pelos membros da familia, mas outra pessoa que nao seje da familia nao tem acesso a esse tipo de coisa.
Static -> não pode acessar qualquer outro atributo ou método da classe que também não seja estático. A vantagem é que se não se precisa instanciar um objeto para acessar-los. Exemplo:
Public, protected e private são tipos de visibilidade. Estáticos e não-estáticos tem a ver com escopo. Não misture ambas e não tente pensar no mundo real para entender orientação a objetos.
Se a classe não fosse estática precisaríamos instanciar um objeto Valida, o que consumiria mais recursos e daria um código mais longo e menos legível.
A OO é verbosa por natureza. No caso de validação, não criaríamos um método para uma validação, pois iria violar o Open/Closed Principle e o Single Responsibility Principle, que são relevantes para um bom design.
interface Rule
{
public function isValid();
}
class Email implements Rule
{
private $email;
public function __construct($email)
{
$this->email = $email;
}
public function isValid()
{
return filter_var($this->email, FILTER_VALIDATE_EMAIL) !== false;
}
}
class CPF implements Rule
{
private $cpf;
public function __construct($cpf)
{
$this->cpf = $cpf;
}
public function isValid()
{
$c = preg_replace('/\D/', '', $this->cpf);
if (strlen($c) != 11 || preg_match("/^{$c[0]}{11}$/", $c)) {
return false;
}
for ($s = 10, $n = 0, $i = 0; $s >= 2; $n += $c[$i++] * $s--);
if ($c[9] != ((($n %= 11) < 2) ? 0 : 11 - $n)) {
return false;
}
for ($s = 11, $n = 0, $i = 0; $s >= 2; $n += $c[$i++] * $s--);
if ($c[10] != ((($n %= 11) < 2) ? 0 : 11 - $n)) {
return false;
}
return true;
}
}
class Validator
{
private $rules = [];
public function addRule(Rule $rule)
{
$this->rules[] = $rule;
return $this;
}
public function validate()
{
foreach ($this->rules as $rule) {
if (! $rule->isValid()) {
// Procedimentos quando há uma falha
} else {
// Procedimentos quando dá certo
}
}
}
}
$validator = new Validator();
$validator->addRule(new Email($_POST['email']))
->addRule(new CPF($_POST['cpf']))
->validate();@Enrico Pereira, muito boa sua contribuição!!!
OFF
Tenho que tirar o chapeu!!!
Não sei se entendi muito bem suas colocações.
um método / atributo estático não pode acessar qualquer outro atributo ou método da classe que também não seja estático. A vantagem é que se não se precisa instanciar um objeto para acessar-los.
Teoricamente de dentro dos escopo da classe o correto é usar self::$variavel ou self::funcao mas acredito que o $this-> funcione da mesma maneira.
De fora da classe você pode acessa-los com o nome da classe mais "::" e o método ou atributo estático. ex.: nomedaclasse::$variavel