La programación basada en clases , o más comúnmente orientación a clases , es un estilo de programación orientada a objetos (POO) en el que la herencia ocurre a través de la definición de clases de objetos , en lugar de que la herencia ocurra solo a través de los objetos (compárese con la programación basada en prototipos ).
El modelo más popular y desarrollado de programación orientada a objetos es un modelo basado en clases, en lugar de un modelo basado en objetos. En este modelo, los objetos son entidades que combinan estado (es decir, datos), comportamiento (es decir, procedimientos o métodos ) e identidad (existencia única entre todos los demás objetos). La estructura y el comportamiento de un objeto se definen mediante una clase , que es una definición o plano de todos los objetos de un tipo específico. Un objeto debe crearse explícitamente en función de una clase y un objeto así creado se considera una instancia de esa clase. Un objeto es similar a una estructura , con la adición de punteros de método, control de acceso a miembros y un miembro de datos implícito que ubica instancias de la clase (es decir, objetos de la clase) en la jerarquía de clases (esencial para las características de herencia en tiempo de ejecución).
La encapsulación evita que los usuarios rompan las invariantes de la clase, lo que resulta útil porque permite cambiar la implementación de una clase de objetos por aspectos no expuestos en la interfaz sin afectar al código del usuario. Las definiciones de encapsulación se centran en la agrupación y el empaquetado de información relacionada ( cohesión ) en lugar de en cuestiones de seguridad.
En la programación basada en clases, la herencia se realiza definiendo nuevas clases como extensiones de clases existentes: la clase existente es la clase padre y la nueva clase es la clase hija . Si una clase hija tiene solo una clase padre, esto se conoce como herencia simple , mientras que si una clase hija puede tener más de una clase padre, esto se conoce como herencia múltiple . Esto organiza las clases en una jerarquía , ya sea un árbol (si es herencia simple) o un entramado (si es herencia múltiple).
La característica que define la herencia es que se heredan tanto la interfaz como la implementación; si solo se hereda la interfaz, esto se conoce como herencia de interfaz o subtipificación. La herencia también se puede realizar sin clases, como en la programación basada en prototipos .
Los lenguajes basados en clases, o, para ser más precisos, los lenguajes tipados , donde la subclasificación es la única forma de subtipificar , han sido criticados por mezclar implementaciones e interfaces, el principio esencial en la programación orientada a objetos. Los críticos dicen que uno podría crear una clase bag que almacene una colección de objetos, luego extenderla para hacer una nueva clase llamada clase set donde se elimina la duplicación de objetos. [1] [2] Ahora, una función que toma un objeto de la clase bag puede esperar que agregar dos objetos aumente el tamaño de una bolsa en dos, pero si uno pasa un objeto de una clase set, entonces agregar dos objetos puede o no aumentar el tamaño de una bolsa en dos. El problema surge precisamente porque la subclasificación implica subtipificación incluso en los casos en que el principio de subtipificación, conocido como el principio de sustitución de Liskov , no se cumple. Barbara Liskov y Jeannette Wing formularon el principio sucintamente en un artículo de 1994 de la siguiente manera:
Requisito de subtipo : Sea una propiedad demostrable sobre objetos del tipo . Entonces debería ser verdadero para objetos del tipo donde es un subtipo de .
Por lo tanto, normalmente se debe distinguir entre subtipos y subclases. La mayoría de los lenguajes orientados a objetos actuales distinguen entre subtipos y subclases, pero algunos enfoques de diseño no lo hacen.
Además, otro ejemplo común es que un objeto persona creado a partir de una clase secundaria no puede convertirse en un objeto de la clase principal porque una clase secundaria y una clase principal heredan una clase persona, pero los lenguajes basados en clases en su mayoría no permiten cambiar el tipo de clase del objeto en tiempo de ejecución. Para los lenguajes basados en clases, esta restricción es esencial para preservar la vista unificada de la clase para sus usuarios. Los usuarios no deberían tener que preocuparse si una de las implementaciones de un método causa cambios que rompan las invariantes de la clase. Tales cambios se pueden hacer destruyendo el objeto y construyendo otro en su lugar. El polimorfismo se puede utilizar para preservar las interfaces relevantes incluso cuando se realizan tales cambios, porque los objetos se ven como abstracciones de caja negra y se accede a ellos a través de object identity . Sin embargo, generalmente se cambia el valor de las referencias de objeto que se refieren al objeto, lo que causa efectos en el código del cliente.
Aunque Simula introdujo la abstracción de clases, el ejemplo canónico de un lenguaje basado en clases es Smalltalk . Otros lenguajes basados en clases son PHP , C++ , Java , C# y Objective-C .