php - que - Mejores prácticas, anulando__construct() en lugar de proporcionar el método init()
que es un constructor en php (5)
Cuando está subclasificando objetos y desea extender el código de inicialización, hay dos enfoques. Anulando a __construct () e implementando un método de inicialización al que llama su constructor de superclase.
Método 1:
class foo
{
public function __construct ($arg1, $arg2, $arg3)
{
// Do initialization
}
}
class bar extends foo
{
public function __construct ($arg1, $arg2, $arg3)
{
parent::__construct ($arg1, $arg2, $arg3);
// Do subclass initialization
}
}
Método 2
class foo
{
public function init ()
{
// Dummy function
}
public function __construct ($arg1, $arg2, $arg3)
{
// Do subclass defined initialization
$this -> init ();
// Do other initialization
}
}
class bar extends foo
{
public function init ()
{
// Do subclass initialization
}
}
La documentación de Zend Framework parece desalentar a los constructores de anulación y desea que anule los métodos de inicio, cuando se proporcionen, pero de alguna manera esto no me parece correcto. Zend también tiende a hacer algunas cosas con las que no estoy contento, así que no estoy seguro de que deba usarse como un ejemplo de la mejor práctica. Personalmente creo que el primer enfoque es el correcto, pero he visto el segundo enfoque con la frecuencia suficiente para preguntarme si eso es realmente lo que debería estar haciendo.
¿Tiene algún comentario con respecto a reemplazar __construct? Sé que tienes que tener cuidado de recordar invocar al constructor de la superclase, pero la mayoría de los programadores deben ser conscientes de eso.
EDIT: No estoy usando Zend, solo lo estoy usando como un ejemplo de un código base que lo alienta a usar init () en lugar de anular __construct ().
Las únicas dos situaciones en las que puedo pensar que tiene sentido utilizar init()
es cuando su constructor no es público, pero necesita darle a las personas la oportunidad de influir en la inicialización, por ejemplo, en un Singleton abstracto (que no desea utilizar de todos modos). O, como en Zend Framework, cuando se debe diferir la inicialización adicional (pero luego no se llama a init()
desde el constructor).
Llamar a un método en una subclase de la superclase se denomina Método de plantilla , por cierto. El UseCase sería organizar un flujo de trabajo determinado pero permitir que el subtipo influya en partes de él. Esto generalmente se hace de métodos regulares sin embargo. Tenga en cuenta que su constructor no debe organizar nada, sino simplemente inicializar el objeto en un estado válido .
Definitivamente no deberías llamar / ofrecer init()
desde el constructor para evitar que los desarrolladores tengan que recordar llamar al constructor de supertipo. Si bien eso puede parecer conveniente, ensuciará rápidamente la jerarquía de herencia. También tenga en cuenta que se desvía de la forma en que normalmente se inicializan los objetos y los desarrolladores tienen que aprender este nuevo comportamiento, al igual que tienen que aprender a llamar al constructor del supertipo.
Parece que el segundo enfoque es posponer el problema.
Si tienes una clase:
class bar2 extends bar // which already extends foo
{
public function init()
{
// You should then do anyway:
parent::init();
// ...
}
}
También buscaría el primer enfoque, más lógico y directo, ya que la llamada parent::init()
o parent::__construct()
no se pudo evitar sin cesar. El primer enfoque, IMO, es menos confuso.
Puedo ver un beneficio al usar init()
lugar de __construct()
: si la firma cambia en el constructor, tendrá que actualizar cada clase derivada para que coincida con la nueva firma.
Si init()
no tiene ningún parámetro, esto no sucederá.
Yo usaría la función de inicio porque si reemplaza al constructor, (normalmente) debe recordar llamar al constructor principal en la parte superior del constructor de la clase secundaria. Si bien puede estar al tanto de eso, no puede garantizar que otro desarrollador encargado de mantener su aplicación lo sea.
en primer lugar
Zend también tiende a hacer algunas cosas con las que no estoy contento.
Puedes resolver esto simplemente, no usándolo.
Pero en segundo lugar, y más importante, debe reemplazar a init()
y no a __construct()
porque init()
es parte de la operación de envío que Zend usa y asegura que el resto de su aplicación está allí y en su lugar. De lo contrario, se interrumpe el flujo del modelo MVC de Zend y puede resultar en un comportamiento extraño.
Editar
Creo que la principal razón para mí es que evita que otros desarrolladores se involucren. Puede hacer cualquier cosa con init()
pero no con __construct()
ya que esto necesita ejecutarse correctamente con todos los parámetros correctos en su lugar.
Esto es de los documentos de Zend:
Si bien siempre puede anular el constructor del controlador de acción, no lo recomendamos. Zend_Controller_Action :: _ construct () realiza algunas tareas importantes, como registrar los objetos de solicitud y respuesta, así como los argumentos de invocación personalizados que se pasan desde el controlador frontal. Si debe anular el constructor, asegúrese de llamar a parent :: _construct ($ request, $ response, $ invokeArgs).