O que significa novo eu (); significa em PHP?

110

Nunca vi um código como este:

public static function getInstance()
{
    if ( ! isset(self::$_instance)) {
        self::$_instance = new self();
    }
    return self::$_instance;
}

É o mesmo que new className()?

EDITAR

Se a classe for hereditária, para qual classe ela aponta?

user198729
fonte
@ stereofrog, você quer dizer que o padrão singleton deve ser abandonado? Mas todas as coisas existem por uma razão, certo?
user198729
Oh, tendo a concordar com este ponto: singleton deve ser substituído por fábrica
usuário 198729
@stereofrog Singleton são venenosos para o teste de unidade, é extremamente difícil fazer testes imutáveis ​​em algo que muda de estado de uma chamada para a próxima.
David,
Infelizmente, esse método não se estenderá. Sempre lhe dará um novo objeto da classe na qual esta função foi definida.
Ares,

Respostas:

211

self aponta para a classe em que está escrito.

Portanto, se o método getInstance estiver em um nome de classe MyClass, a seguinte linha:

self::$_instance = new self();

Fará o mesmo que:

self::$_instance = new MyClass();



Edit: mais algumas informações, após os comentários.

Se você tiver duas classes que se estendem, você terá duas situações:

  • getInstance é definido na classe filha
  • getInstance é definido na classe pai

A primeira situação ficaria assim (removi todo o código não necessário, para este exemplo - você terá que adicioná-lo de volta para obter o comportamento do singleton) *:

class MyParentClass {

}
class MyChildClass extends MyParentClass {
    public static function getInstance() {
        return new self();
    }
}

$a = MyChildClass::getInstance();
var_dump($a);

Aqui, você obterá:

object(MyChildClass)#1 (0) { } 

O que significa selfsignifica MyChildClass- ou seja, a classe em que está escrito.


Para a segunda situação, o código seria assim:

class MyParentClass {
    public static function getInstance() {
        return new self();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

E você obteria este tipo de saída:

object(MyParentClass)#1 (0) { }

O que significa selfsignifica MyParentClass- ou seja, aqui também, a classe em que está escrito .




Com o PHP <5.3, que "a classe na qual está escrito" é importante - e às vezes pode causar problemas.

É por isso que o PHP 5.3 introduz um novo uso para a staticpalavra-chave: agora ela pode ser usada exatamente onde usamos selfnesses exemplos:

class MyParentClass {
    public static function getInstance() {
        return new static();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Mas, em staticvez de self, você agora obterá:

object(MyChildClass)#1 (0) { } 

O que significa que staticisso aponta para a classe que é usada (nós usamos MyChildClass::getInstance()), e não para aquela em que está escrita.

Claro, o comportamento do selfnão foi alterado, para não quebrar os aplicativos existentes - o PHP 5.3 acabou de adicionar um novo comportamento, reciclando a staticpalavra - chave.


E, falando sobre PHP 5.3, você pode querer dar uma olhada na página Late Static Bindings do manual do PHP.

Pascal MARTIN
fonte
@Paul: heu ... significa "self atua como um apelido para" ou "self meio que aponta para" - o verbo "designer", em francês, pode ser usado para isso - suponho que seja uma das situações em que usar a mesma palavra em inglês não é uma boa ideia ;-( Editarei minha resposta para corrigir isso ;; obrigado :-)
Pascal MARTIN
E se houver baseclass, classque se faz isso aponta para?
user198729
@ usuário: Eu editei minha resposta para dar mais informações sobre selfherança; e também incluí algumas informações sobre staticno PHP 5.3 ;; espero que isso ajude :-)
Pascal MARTIN
10

Esta parece ser uma implementação do padrão Singleton . A função é chamada estaticamente e verifica se a classe estática tem a variável $_instancedefinida.

Se não for, ele inicializa uma instância de si mesmo ( new self()) e a armazena em $_instance.

Se você chamar className::getInstance(), obterá uma e a mesma instância de classe em todas as chamadas, que é o ponto do padrão singleton.

Eu nunca vi isso ser feito dessa forma, porém, e honestamente não sabia que era possível. O que é $_instancedeclarado na classe?

Pekka
fonte
1
$_instanceé declarado comopublic static $_instance;
Atif
7

Isso é mais provavelmente usado no padrão de design singleton, em que o construtor é definido como privado para evitar ser instanciado, o (::)operador de dois pontos duplos pode acessar membros que são declarados estáticos dentro da classe, portanto, se houver membros estáticos, a pseudo variável $ isso não pode ser usado, portanto, o código usado self em vez disso. Singletons são boas práticas de programação que permitirão apenas 1 instância de um objeto como manipuladores de conector de banco de dados. A partir do código do cliente, o acesso a essa instância seria feito através da criação de um único ponto de acesso, neste caso ele o nomeou getInstance(), O getInstance em si foi a função que criou o objeto basicamente usando a nova palavra-chave para criar um objeto, o que significa que o método construtor foi também chamado.

a linha if(!isset(self::instance))verifica se um objeto já foi criado, você não pode entender isso porque o código é apenas um fragmento, em algum lugar no topo, deve haver membros estáticos como provavelmente

private static $_instance = NULL; 

em classes normais, teríamos acessado este membro simplesmente

$this->_instance = 'something';

mas é declarado como estático e, portanto, não podemos usar o código $ this que usamos

self::$_instance

verificando se há um objeto armazenado nesta variável de classe estática, a classe pode então decidir criar ou não criar uma única instância, portanto, se não estiver definido,! isset, o que significa que nenhum objeto existe no membro estático $ _instance, então ele gera um novo objeto, armazenado no membro estático $_instancepelo comando

self::$_instance = new self();

e o devolveu ao código do cliente. O código do cliente pode então usar alegremente a única instância do objeto com seus métodos públicos, mas no código do cliente, chamando o único ponto de acesso, ou seja, o getInstance()método também é complicado, tem que ser chamado assim

$thisObject = className::getInstance();

a razão, a função em si é declarada estática.

flimh
fonte
2

Sim, é como new className()(referindo-se à classe que contém esse método), provavelmente usado em um padrão Singleton onde o construtor é privado.

Matteo Riva
fonte
Por que alguém usaria o padrão Singleton em PHP? A menos que seja usado em um programa semelhante a um daemon, o singleton só viverá enquanto o script for executado e desaparecerá junto com o programa.
ILikeTacos
4
para evitar irritantemente declarar global para acessar uma variável global
Sam Adamsh
0

Se a classe for herdada, chamar getInstance () de child não fornecerá uma instância de child. Ele retornará apenas uma instância da instância pai. Isso ocorre porque chamamos de novo self ().

Se você quiser que a classe filha retorne uma instância da classe filha, use new static () em getInstance () e ela retornará a instância da classe filha. Isso é chamado de ligação tardia !!

kta
fonte