PHP - Duda sobre las clases y metodos abstractos

LzO

Pues por más que busco en internet, no encuentros ejemplos claros...

No me entra en la cabeza, para que es necesario usar los metodos o clases abstractas...

Hablamos de PHP POO.

No se ni para que sirve, ni para que es necesario, o si debo o no usarlo o en que circunstancias...

Tengo un ejemplo que no usa abstract:

spoiler

Y otro que si lo usa:

spoiler

Ahora, me temía lo siguiente, yo dandole vueltas a la cabeza y es que si borro la palabra "abstract" de la primera linea "abstract class figura" y tambien borro la linea completa de "abstract public function area();" sigue funcionando a la perfeccion... la unica diferencia de los dos codigos es que uno usa herencias y el otro switch (pero no viene al caso con mi duda).

Pero ya os digo, me vino a la cabeza de borrar esas palabras que os dije y eureca! sigue funcionando.

a ver si algún experto me explica... cuando, porque y para que, se usan los metodos y clases abstractos.

Muchas gracias.

LOc0

Échale un vistazo a:

http://php.net/manual/es/language.oop5.abstract.php

http://www.fluffycat.com/PHP-Design-Patterns/

http://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o

Salu2 ;)

1 1 respuesta
LzO

#2 Sigo igual, y esas webs las descarto, en la primera que siempre visito para dudas, aún salgo con más dudas porque es todo explicado muy a lo entendido.

La segunda no me entero ni papa.

Y la otra, pues, ladrillos everywhere, y no me despeja ninguna duda...

Pero se agradece el interés :D

1 respuesta
LOc0

#3

PHP 5 introduce clases y métodos abstractos. Las clases definidas como abstract seguramente no son instanciadas y cualquier clase que contiene almenos un método abstracto debe ser definida como abstract. Los métodos definidos como abstractos simplemente declaran la estructura del método, pero no pueden definir la implementación.

Cuando se hereda de una clase abstracta, todos los métodos definidos como abstract en la definición de la clase parent deben ser redefinidos en la clase child; adicionalmente, estos métodos deben ser definidos con la misma visibilidad (o con una menos restrictiva). Por ejemplo, si el método abstracto está definido como protected, la implementación de la función puede ser redefinida como protected o public, pero nunca como private. Por otra parte, las estructuras de los métodos tienen que coincidir, es decir, los (type hinting) tipos sugeridos y el número de argumentos requeridos deben ser los mismos. Esto también aplica a los constructores de PHP 5.4. Antes de PHP 5.4 las estructuras del constructor podían ser diferentes.

¿Qué parte de ese texto no comprendes? EN SERIO :O

Salu2 ;)

PD: si quieres saber por qué el código funciona borrando ABSTRACT es porque lo estás haciendo menos restrictivo, pero NO tiene la misma semántica, vamos, que NO ES LO MISMO.

PD2: ¿has estudiado algo de Programación Orientada a Objetos? (No va a malas, ¿eh?) -> http://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos

1 1 respuesta
LzO

#4 Pues más bien no es que no lo comprenda (que un poco si es liante el texto, con tanto tecnicismo) más bien mi duda es:

cuando, porque y para que usar una clase/método abstracto.

Gracias.

edit: si que he estudiado... clases, propiedades, metodos, constructores, destructores, visibilidad, herencia, operadores de ambitos, clonacion, modificadores de accesos, sobreescritura...

Pero el tema abstracto, como que no me entra.

2 respuestas
cabron

#5

Un método abstracto lo usas cuando quieres llamar a un método que puede tener más de una implementación, pero a ti te da igual que haya una o mil.

En el ejemplo que has puesto, cada tipo de figura calcula del área de forma diferente. A ti lo que te importa es mostrar el área de la figura que tienes en ese momento, no te importa el tipo de figura ni la fórmula que use esa figura para calcular el área.

Usando el método abstracto, simplemente te preocupas de llamara a area() te da igual si lo que hay en la variable es un triángulo, un rectángulo, u otra figura diferente.

2
B

#5 Básicamente una clase abstracta define métodos que deben ser implementados por parte de la clase que la use. Fuerza a que existan si o si y cada clase puede implementarlos de una forma u otra.

1
cabron

De todas formas, el motivo por el que sigue funcionando es por que PHP tiene tipado dinámico y en una variable puedes meter cualquier cosa.

Te recomiendo que aunque lo vayas a usar con PHP, mires como sería en un lenguaje de tipado estático como Java, donde tendrías que declarar la variable con el tipo de la clase abstracta y solo te deja meter en la variable subclases, en mi opinión lo vas a ver más claro.

1
C

#1, has planteado una de las cuestiones vitales de la OOP y lo mejor es que has puesto dos buenos trozos de código para enteder las diferencias. Es más, se me ocurre un tercer ejemplo más, pero es tarde ya.

Quizás te parezca que las dos hacen lo mismo (y así es). Pero no lo hacen de la misma forma. Para ver la diferencia, y descubrir una de las bondades de la OOP (hay más), piensa por un momento que en vez de tener dos figuras (triángulo y rectángulo), tuvieras 20 figuras distintas. ¿Cómo sería la clase no abstracta? Enooorme. Y con ello una probabilidad enooorme de tener que retocar la clase más veces y romper el resto del funcionamiento de la clase (aunque te parezca que un switch encapsula el comportamiento).

¿Y si en vez de una única función como la que tienes ahora (area), tuvieras que incorporar 30 funciones más? ¿Cómo de grande sería tu clase y cuántas veces tendrías que tocarla?

Siguiendo en esta línea de tener nuevas funciones:
¿Y si ahora quisieras almacenar en una base de datos tus figuras?
En la solución no-OOP tendrías que implementar en cada 'case' del 'switch' un copy&paste de la función 'GrabarFiguraEnBaseDeDatos'. Con la solución OOP tendrías ese método en la clase abstracta. Y si los datos que guardas son comunes en todas las clases derivadas, entonces podrías implementar ese método en la clase padre y te ahorrarías el copy&paste. ¿Y si un día tienes que tocar esa función que inserta en la base de datos? Pues la tocas una vez y no ochocientas.

¿Y si quisieras realizar operaciones con tus figuras? En la solución no-OOP tendrías que crear dos objetos figura y esas operaciones (funciones) tendría que estar dentro de tu ya mega-clase teniendo que hacer comparaciones entre los tipos de figura.
Con la solución OOP tendrías el método de la operación en la clase abstracta ya que en esa clase se pueden manejar propiedades que tienen en común por ser figuras (su clase padre). Aunque, obviamente la clase padre no ve las implementaciones particulares de las hijas. Sería sólo para propiedades comunes a todas.

Y volviendo a tu primer código no-OOP, ¿y si ahora resulta que la nueva figura no sólo tiene base y altura sino radio porque es un círculo? (típico ejemplo). ¿Modificas el constructor de tu clase figura con ochocientos parámetros? ¿Generas n-constructores distintos por cada figura?
Con la solución OOP, cada clase derivada de la abstracta tiene su propio constructor y llamaría al de la clase padre pasándole sólo aquellas propiedades heredadas y comunes a su padre. Pero la implementación específica la tendría la derivada.

En fin, que estoy escribiendo al tuntun y es tarde y tengo la cabeza embotada. Pero aunque en esos casos te parezca igual, te aseguro que un proyecto gordo de cientos de miles de líneas de código es más fácil tocar en un único sitio que en ochocientos. Y no quiere decir que la OOP sea un camino de rosas. Mal entendida y aplicada se vuelve rígida e inútil. Y uno acaba por hacer un pan con unas ostias al acabar programando de forma estructurada pero creando clases (es lo peor que puedes ver en el mundo real y yo lo he visto! xD).

Todo se resume en: encapsulación, reutilización, pero sobre todo (y esto se descubre con el tiempo) polimorfismo. Bendito polimorfismo la cantidad de copy&paste que ahorra y, por ende, errores.

Si sigues sin entender nada, lo dices e intentamos de nuevo con más ejemplos. Para eso estamos! ;)

2
LzO

gracias a todos chicos

Usuarios habituales