usar una programacion modificador metodos instanciar estaticos estaticas ejemplos cuando clases clase php oop class

php - una - Cuándo usar clases estáticas vs instanciadas



static java (10)

¿Es todo solo estilo?

Un largo camino, sí. Puede escribir programas perfectamente orientados a objetos sin usar miembros estáticos. De hecho, algunas personas argumentarían que los miembros estáticos son una impureza en primer lugar. Sugeriría que, como principiante en oop, intente evitar miembros estáticos todos juntos. Te forzará a escribir en un estilo orientado a objetos en lugar de a un estilo de procedimiento .

PHP es mi primer lenguaje de programación. No puedo entender bien cuándo utilizar clases estáticas frente a objetos instanciados.

Me doy cuenta de que puedes duplicar y clonar objetos. Sin embargo, en todo mi tiempo usando php cualquier objeto o función siempre terminaba como un único valor de retorno (matriz, cadena, int) o vacío.

Comprendo conceptos en libros como una clase de personaje de videojuego. duplicar el objeto del coche y hacer que el nuevo rojo , que todo tiene sentido, pero lo que no es su aplicación en php y aplicaciones web.

Un simple ejemplo. Un blog. ¿Qué objetos de un blog se implementarían mejor como objetos estáticos o instanciados? La clase DB? ¿Por qué no simplemente instanciar el objeto db en el ámbito global? ¿Por qué no hacer cada objeto estático en su lugar? ¿Qué hay del rendimiento?

¿Es todo solo estilo? ¿Hay una forma adecuada de hacer esto?


"Tener una llamada de método estático dentro de otro método es en realidad peor que importar una variable global". (definir "peor") ... y "Los métodos estáticos que no tratan con propiedades estáticas deben ser funciones".

Estas son declaraciones bastante amplias. Si tengo un conjunto de funciones relacionadas en el tema, pero los datos de la instancia son totalmente inapropiados, preferiría tenerlos definidos en una clase y no cada uno de ellos en el espacio de nombres global. Solo estoy usando los mecanismos disponibles en PHP5 para

  • darles a todos un espacio de nombres, evitando cualquier conflicto de nombre
  • mantenerlos físicamente ubicados juntos en lugar de dispersarse en un proyecto; otros desarrolladores pueden encontrar más fácilmente lo que ya está disponible y es menos probable que reinventen la rueda
  • permítanme usar conste de clase en lugar de define global para cualquier valor mágico

es simplemente una forma conveniente de reforzar una mayor cohesión y un menor acoplamiento.

Y FWIW - no existe tal cosa, al menos en PHP5, como "clases estáticas"; los métodos y las propiedades pueden ser estáticos. Para evitar la creación de instancias de la clase, también se puede declarar abstracto.


Aquí tengo un enfoque diferente para la mayoría de las respuestas, especialmente cuando uso PHP. Creo que todas las clases deben ser estáticas a menos que tengas una buena razón por la que no. Algunas de las razones de "por qué no" son:

  • Necesita varias instancias de la clase
  • Tu clase necesita ser extendida
  • Partes de tu código no pueden compartir las variables de clase con otras partes

Déjame tomar un ejemplo. Como cada script PHP produce código HTML, mi framework tiene una clase de escritor html. Esto asegura que ninguna otra clase intentará escribir HTML, ya que es una tarea especializada que debe concentrarse en una sola clase.

Normalmente, usaría la clase html de esta manera:

html::set_attribute(''class'',''myclass''); html::tag(''div''); $str=html::get_buffer();

Cada vez que se llama a get_buffer (), restablece todo para que la siguiente clase que utiliza el escritor html se inicie en un estado conocido.

Todas mis clases estáticas tienen una función init () que necesita ser llamada antes de que la clase se use por primera vez. Esto es más por convención que una necesidad.

La alternativa a una clase estática en este caso es desordenada. No querría que todas las clases que necesitan escribir un poquito de html tengan que administrar una instancia del escritor html.

Ahora le daré un ejemplo de cuándo no usar clases estáticas. Mi clase de formulario administra una lista de elementos de formulario como entradas de texto, listas desplegables y más. Por lo general, se usa así:

$form = new form(stuff here); $form->add(new text(stuff here)); $form->add(new submit(stuff here)); $form->render(); // Creates the entire form using the html class

No hay forma de que pueda hacer esto con clases estáticas, especialmente teniendo en cuenta que algunos de los constructores de cada clase agregada hacen mucho trabajo. Además, la cadena de herencia para todos los elementos es bastante compleja. Entonces este es un claro ejemplo donde las clases estáticas no deberían ser usadas.

La mayoría de las clases de utilidad, como las que convierten / formatean cadenas, son buenas candidatas para ser una clase estática. Mi regla es simple: todo se vuelve estático en PHP a menos que haya una razón por la que no debería ser así.


En general, debe usar las variables de miembro y las funciones de miembro a menos que sea absolutamente necesario compartirlas entre todas las instancias o a menos que esté creando un singleton. El uso de datos de miembros y funciones de miembros le permite reutilizar sus funciones para múltiples piezas de datos diferentes, mientras que solo puede tener una copia de los datos en los que opera si utiliza datos y funciones estáticas. Además, aunque no es aplicable a PHP, las funciones estáticas y los datos llevan a que el código no sea reentrante, mientras que los datos de clase facilitan la reentrada.


Entonces en PHP static se puede aplicar a funciones o variables. Las variables no estáticas están vinculadas a una instancia específica de una clase. Los métodos no estáticos actúan en una instancia de una clase. Así que BlogPost una clase llamada BlogPost .

title sería un miembro no estático. Contiene el título de esa publicación de blog. También podríamos tener un método llamado find_related() . No es estático porque requiere información de una instancia específica de la clase de publicación de blog.

Esta clase se vería así:

class blog_post { public $title; public $my_dao; public function find_related() { $this->my_dao->find_all_with_title_words($this->title); } }

Por otro lado, usando funciones estáticas, puedes escribir una clase como esta:

class blog_post_helper { public static function find_related($blog_post) { // Do stuff. } }

En este caso, dado que la función es estática y no está actuando en ninguna publicación de blog en particular, debe pasar la publicación de blog como argumento.

Fundamentalmente, esta es una pregunta sobre el diseño orientado a objetos. Sus clases son los sustantivos en su sistema, y ​​las funciones que actúan sobre ellos son los verbos. Las funciones estáticas son de procedimiento. Usted pasa el objeto de las funciones como argumentos.

Actualización: También agregaría que la decisión rara vez es entre métodos de instancia y métodos estáticos, y más entre el uso de clases y el uso de matrices asociativas. Por ejemplo, en una aplicación de blog, puede leer publicaciones de blog de la base de datos y convertirlas en objetos, o las deja en el conjunto de resultados y las trata como matrices asociativas. Luego, escribe funciones que toman matrices asociativas o listas de matrices asociativas como argumentos.

En el escenario OO, escribe métodos en su clase BlogPost que actúan en publicaciones individuales, y escribe métodos estáticos que actúan en colecciones de publicaciones.


Esta es una pregunta bastante interesante, y las respuestas también pueden ser interesantes ^^

La forma más simple de considerar las cosas podría ser:

  • utilizar una clase instanciada donde cada objeto tiene datos propios (como un usuario tiene un nombre)
  • use una clase estática cuando es solo una herramienta que funciona en otras cosas (como, por ejemplo, un convertidor de sintaxis para código BB a HTML; no tiene vida propia)

(Sí, lo admito, realmente demasiado simplificado ...)

Una cosa sobre los métodos / clases estáticos es que no facilitan las pruebas unitarias (al menos en PHP, pero probablemente también en otros idiomas).

Otra cosa sobre los datos estáticos es que solo existe una instancia de esto en su programa: si establece MyClass :: $ myData en algún lugar, tendrá este valor, y solo en cada lugar - Hablando del usuario, usted podría tener solo un usuario, que no es tan bueno, ¿verdad?

Para un sistema de blog, ¿qué podría decir? No hay mucho que escribiría como estático, en realidad, creo; tal vez la clase de acceso DB, pero probablemente no, al final ^^


Las dos razones principales contra el uso de métodos estáticos son:

  • código usando métodos estáticos es difícil de probar
  • código usando métodos estáticos es difícil de extender

Tener una llamada de método estático dentro de otro método es peor que importar una variable global. En PHP, las clases son símbolos globales, por lo que cada vez que llamas a un método estático dependes de un símbolo global (el nombre de la clase). Este es un caso cuando global es malvado. Tuve problemas con este tipo de enfoque con algún componente de Zend Framework. Hay clases que usan llamadas a métodos estáticos (fábricas) para construir objetos. Me fue imposible suministrar otra fábrica a esa instancia para obtener un objeto personalizado devuelto. La solución a este problema es usar instancias y métodos de instance y aplicar singletons y similares al principio del programa.

Miško Hevery , que trabaja como Coach Ágil en Google, tiene una teoría interesante, o más bien aconseja, que deberíamos separar el tiempo de creación del objeto desde el momento en que usamos el objeto. Entonces, el ciclo de vida de un programa se divide en dos. La primera parte (el método main() digamos), que se encarga de todo el cableado de objetos en su aplicación y la parte que hace el trabajo real.

Entonces, en lugar de tener:

class HttpClient { public function request() { return HttpResponse::build(); } }

Deberíamos hacer:

class HttpClient { private $httpResponseFactory; public function __construct($httpResponseFactory) { $this->httpResponseFactory = $httpResponseFactory; } public function request() { return $this->httpResponseFactory->build(); } }

Y luego, en el índice / página principal, lo haríamos (este es el paso de cableado del objeto, o el momento de crear el gráfico de las instancias que usará el programa):

$httpResponseFactory = new HttpResponseFactory; $httpClient = new HttpClient($httpResponseFactory); $httpResponse = $httpClient->request();

La idea principal es desacoplar las dependencias de tus clases. De esta forma, el código es mucho más extensible y, la parte más importante para mí, comprobable. ¿Por qué es más importante ser comprobable? Porque no siempre escribo el código de la biblioteca, por lo que la extensibilidad no es tan importante, pero la capacidad de prueba es importante cuando realizo la refactorización. De todos modos, el código comprobable generalmente arroja un código extensible, por lo que no es una situación real.

Miško Hevery también hace una clara distinción entre Singletons y Singletons (con o sin una S mayúscula). La diferencia es muy simple. Los singletons con una minúscula "s" son aplicados por el cableado en el índice / principal. Instancias un objeto de una clase que no implementa el patrón Singleton y cuidas de pasar esa instancia solo a cualquier otra instancia que lo necesite. Por otro lado, Singleton, con una "S" mayúscula es una implementación del patrón (anti) clásico. Básicamente un mundo disfrazado que no tiene mucho uso en el mundo de PHP. No he visto uno hasta este punto. Si desea que todas sus clases utilicen una única conexión de BD, es mejor hacerlo así:

$db = new DbConnection; $users = new UserCollection($db); $posts = new PostCollection($db); $comments = new CommentsCollection($db);

Al hacer lo anterior, está claro que tenemos un singleton y también tenemos una buena manera de inyectar un simulacro o un stub en nuestras pruebas. Es sorprendente cómo las pruebas unitarias conducen a un mejor diseño. Pero tiene mucho sentido cuando crees que las pruebas te obligan a pensar en la forma en que usarías ese código.

/** * An example of a test using PHPUnit. The point is to see how easy it is to * pass the UserCollection constructor an alternative implementation of * DbCollection. */ class UserCollection extends PHPUnit_Framework_TestCase { public function testGetAllComments() { $mockedMethods = array(''query''); $dbMock = $this->getMock(''DbConnection'', $mockedMethods); $dbMock->expects($this->any()) ->method(''query'') ->will($this->returnValue(array(''John'', ''George''))); $userCollection = new UserCollection($dbMock); $allUsers = $userCollection->getAll(); $this->assertEquals(array(''John'', ''George''), $allUsers); } }

La única situación en la que usaría (y los he usado para imitar el objeto prototipo de JavaScript en PHP 5.3) miembros estáticos es cuando sé que el campo respectivo tendrá el mismo valor de instancia cruzada. En ese punto, puede usar una propiedad estática y tal vez un par de métodos estáticos getter / setter. De todos modos, no olvide agregar la posibilidad de anular el miembro estático con un miembro de instancia. Por ejemplo, Zend Framework usaba una propiedad estática para especificar el nombre de la clase de adaptador DB utilizada en instancias de Zend_Db_Table . Ha pasado un tiempo desde que los usé, por lo que puede que ya no sea relevante, pero así es como lo recuerdo.

Los métodos estáticos que no tratan con propiedades estáticas deben ser funciones. PHP tiene funciones y deberíamos usarlas.


Me gustaría decir que definitivamente hay un caso en el que me gustaría tener variables estáticas en aplicaciones de varios idiomas. Podrías tener una clase a la que le pasas un idioma (p. Ej., $ _SESSION [''language'']) y, a su vez, accederá a otras clases diseñadas de la siguiente manera:

Srings.php //The main class to access StringsENUS.php //English/US StringsESAR.php //Spanish/Argentina //...etc

Usar Strings :: getString ("somestring") es una buena manera de abstraer el uso de su idioma de su aplicación. Puedes hacerlo como quieras, pero en este caso tener cada archivo de cadenas con constantes con valores de cadena a los que se accede por la clase Strings funciona bastante bien.


Primero pregúntate, ¿qué va a representar este objeto? Una instancia de objeto es buena para operar en conjuntos separados de datos dinámicos.

Un buen ejemplo sería ORM o la capa de abstracción de la base de datos. Puede tener múltiples conexiones a la base de datos.

$db1 = new Db(array(''host'' => $host1, ''username'' => $username1, ''password'' => $password1)); $db2 = new Db(array(''host'' => $host2, ''username'' => $username2, ''password'' => $password2));

Esas dos conexiones ahora pueden operar de manera independiente:

$someRecordsFromDb1 = $db1->getRows($selectStatement); $someRecordsFromDb2 = $db2->getRows($selectStatement);

Ahora dentro de este paquete / biblioteca, puede haber otras clases como Db_Row, etc. para representar una fila específica devuelta por una instrucción SELECT. Si esta clase Db_Row fuera una clase estática, eso supondría que solo tiene una fila de datos en una base de datos y sería imposible hacer lo que podría hacer una instancia de objeto. Con una instancia, ahora puede tener un número ilimitado de filas en un número ilimitado de tablas en un número ilimitado de bases de datos. El único límite es el hardware del servidor;).

Por ejemplo, si el método getRows en el objeto Db devuelve una matriz de objetos Db_Row, ahora puede operar en cada fila independientemente el uno del otro:

foreach ($someRecordsFromDb1 as $row) { // change some values $row->someFieldValue = ''I am the value for someFieldValue''; $row->anotherDbField = 1; // now save that record/row $row->save(); } foreach ($someRecordsFromDb2 as $row) { // delete a row $row->delete(); }

Un buen ejemplo de una clase estática sería algo que maneje variables de registro o variables de sesión, ya que solo habrá un registro o una sesión por usuario.

En una parte de tu aplicación:

Session::set(''someVar'', ''toThisValue'');

Y en otra parte:

Session::get(''someVar''); // returns ''toThisValue''

Como solo habrá un usuario a la vez por sesión, no tiene sentido crear una instancia para la sesión.

Espero que esto ayude, junto con las otras respuestas para ayudar a aclarar las cosas. Como nota al margen, revisa " cohesion " y " coupling ". Describen algunas prácticas muy, muy buenas para usar al escribir su código que se aplican a todos los lenguajes de programación.


Si tu clase es estática, significa que no puedes pasar su objeto a otras clases (ya que no hay ninguna instancia posible), eso significa que todas tus clases usarán directamente esa clase estática, lo que significa que tu código ahora está estrechamente relacionado con la clase .

El acoplamiento cerrado hace que su código sea menos reutilizable, frágil y propenso a errores. Desea evitar clases estáticas para poder pasar la instancia de la clase a otras clases.

Y sí, esta es solo una de muchas otras razones, algunas de las cuales ya han sido mencionadas.