oop #oop Tabla de contenido Acerca de 1 Capítulo 1: Empezando con oop 2 Observaciones 2 Examples 2 Introducción 2 OOP Introducción 2 Intoducción 2 Terminología OOP 3 Java 3 C ++ 3 Pitón 3 Java 4 C ++ 4 Pitón 4 Funciones vs Métodos 4 Usando el estado de una clase 5 Interfaces y herencia 6 Clase abstracta Capítulo 2: Abstracción Examples 8 9 9 Abstracción - Introducción 9 Modificadores de acceso 9 Capítulo 3: Clase Examples Introducción Capítulo 4: Encapsulacion Examples Ocultación de información Capítulo 5: Herencia 11 11 11 12 12 12 13 Observaciones 13 Examples 13 Herencia - Definición 13 Ejemplo de herencia - Considera debajo de dos clases 14 Capítulo 6: Objeto Examples Introducción Capítulo 7: Polimorfismo Examples 16 16 16 17 17 Introducción 17 Método de sobrecarga 17 Método Anulando 18 Capítulo 8: Problema del diamante Examples Problema del diamante - Ejemplo Creditos 20 20 20 21 Acerca de You can share this PDF with anyone you feel could benefit from it, downloaded the latest version from: oop It is an unofficial and free oop ebook created for educational purposes. All the content is extracted from Stack Overflow Documentation, which is written by many hardworking individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official oop. The content is released under Creative Commons BY-SA, and the list of contributors to each chapter are provided in the credits section at the end of this book. Images may be copyright of their respective owners unless otherwise specified. All trademarks and registered trademarks are the property of their respective company owners. Use the content presented in this book at your own risk; it is not guaranteed to be correct nor accurate, please send your feedback and corrections to [email protected] https://riptutorial.com/es/home 1 Capítulo 1: Empezando con oop Observaciones La programación orientada a objetos (OOP) es un paradigma de programación basado en el concepto de "objetos", que puede contener datos, en forma de campos, a menudo conocidos como atributos; y el código, en forma de procedimientos, a menudo conocidos como métodos. Examples Introducción OOP - La programación orientada a objetos es un paradigma de programación muy utilizado en estos días. En OOP, modelamos problemas del mundo real utilizando Objetos y comportamientos de ese tipo, para resolverlos mediante programación. Hay cuatro conceptos principales de POO 1. Herencia 2. Polimorfismo 3. Abstracción 4. Encapsulacion Estos cuatro conceptos juntos se utilizan para desarrollar programas en OOP. Hay varios lenguajes que apoyan la Programación Orientada a Objetos. Los idiomas más populares son • • • • C ++ Java DO# Python (Python no está completamente orientado a objetos, pero tiene la mayoría de las características de POO) OOP Introducción Intoducción La Programación Orientada a Objetos (en su mayoría denominada OOP) es un paradigma de programación para resolver problemas. La belleza de un programa OO (orientado a objetos), es que pensamos en el programa como un conjunto de objetos que se comunican entre sí, en lugar de como un script secuencial que sigue órdenes específicas. https://riptutorial.com/es/home 2 Hay muchos lenguajes de programación compatibles con OOP, algunos de los más populares son: • Java • C ++ • do# También se sabe que Python es compatible con OOP, pero carece de algunas propiedades. Terminología OOP El término más básico en OOP es una clase . Una clase es básicamente un objeto , que tiene un estado y funciona de acuerdo con su estado. Otro término importante es una instancia . Piense en una clase como una plantilla utilizada para crear instancias de sí misma. La clase es una plantilla y la (s) instancia (s) son los objetos concretos. Una instancia creada a partir de la clase A generalmente se conoce como del 'tipo A', exactamente como el tipo de 5 es int y el tipo de "abcd" es una cadena . Un ejemplo de creación de una instancia denominada insance1 de tipo (clase) ClassA : Java ClassA instance1 = new ClassA(); C ++ ClassA instance1; o ClassA *instance1 = new ClassA(); # On the heap Pitón instance1 = ClassA() Como puede ver en el ejemplo anterior, en todos los casos se mencionó el nombre de la clase y después había paréntesis vacíos (excepto para C ++ donde, si están vacíos, se pueden quitar los paréntesis). En estos paréntesis podemos pasar arguments al constructor de nuestra clase. Un constructor es un método de una clase que se llama cada vez que se crea una instancia. https://riptutorial.com/es/home 3 Puede tomar argumentos o no. Si el programador no especifica ningún constructor para una clase que construyen, se creará un constructor vacío (un constructor que no hace nada). En la mayoría de los idiomas, el constructor se define como un método sin definir su tipo de retorno y con el mismo nombre de la clase (ejemplo en algunas secciones). Un ejemplo de creación de una instancia denominada b1 de tipo (clase) ClassB . El constructor de ClassB toma un argumento de tipo int : Java ClassA instance1 = new ClassA(5); o int i = 5; ClassA instance1 = new ClassA(i); C ++ ClassA instance1(5); Pitón instance1 = ClassA(5) Como puede ver, el proceso de crear una instancia es muy similar al proceso de llamar a una función. Funciones vs Métodos Tanto las funciones como los métodos son muy similares, pero en el Diseño orientado a objetos (OOD), cada uno tiene su propio significado. Un método es una operación realizada en una instancia de una clase. El método en sí mismo usualmente usa el estado de la instancia para operar. Mientras tanto, una función pertenece a una clase y no a una instancia específica. Esto significa que no utiliza el estado de la clase ni ningún dato almacenado en una instancia. De ahora en adelante, mostraremos nuestros ejemplos solo en Java, ya que OOP es muy claro en este lenguaje, pero los mismos principios funcionan en cualquier otro lenguaje OOP. En Java, una función tiene la palabra estática en su definición, así: // File's name is ClassA public static int add(int a, int b) { return a + b; https://riptutorial.com/es/home 4 } Esto significa que puede llamarlo desde cualquier parte del script. // From the same file System.out.println(add(3, 5)); // From another file in the same package (or after imported) System.out.println(ClassA.add(3, 5)); Cuando llamamos a la función desde otro archivo, usamos el nombre de la clase (en Java, también es el nombre del archivo) al que pertenece, esto da la intuición de que la función pertenece a la clase y no a ninguna de sus instancias. En contraste, podemos definir un método en ClassA así: // File's name is ClassA public int subtract(int a, int b){ return a - b; } Después de esta decleración podemos llamar a este método así: ClassA a = new ClassA(); System.out.println(a.subtract(3, 5)); Aquí necesitamos crear una instancia de ClassA para poder llamar a su método restar. Note que NO PODEMOS hacer lo siguiente: System.out.println(ClassA.subtract(3, 5)); Esta línea producirá un error de compilación quejándose de que llamamos a este método no estático sin una instancia. Usando el estado de una clase Supongamos que queremos implementar nuestro método de resta de nuevo, pero esta vez siempre queremos restar el mismo número (para cada instancia). Podemos crear la siguiente clase: class ClassB { private int sub_amount; public ClassB(int sub_amount) { this.sub_amount = sub_amount; } https://riptutorial.com/es/home 5 public int subtract(int a) { return a - sub_amount; } public static void main(String[] args) { ClassB b = new ClassB(5); System.out.println(b.subtract(3)); // Ouput is -2 } } Cuando ejecutamos este código, se crea una nueva instancia llamada b de la clase ClassB y su constructor se alimenta con el valor 5 . El constructor ahora toma la sub_amount dada y la almacena como su propio campo privado, también llamado sub_amount (esta convención es muy conocida en Java, para nombrar los argumentos igual que los campos). Después de eso, imprimimos a la consola el resultado de llamar al método restar en b con el valor de 3 . Note que en la implementación de restar no usamos this. Como en el constructor. En Java, this solo se debe escribir cuando hay otra variable con el mismo nombre definido en ese ámbito. Lo mismo funciona con la self Python. Entonces, cuando usamos sub_amount en restar, hacemos referencia al campo privado que es diferente para cada clase. Otro ejemplo a destacar. Simplemente cambiemos la función principal en el código anterior a lo siguiente: ClassB b1 = new ClassB(1); ClassB b2 = new ClassB(2); System.out.println(b1.subtract(10)); // Output is 9 System.out.println(b2.subtract(10)); // Output is 8 Como podemos ver, b1 y b2 son independientes y cada uno tiene su propio estado . Interfaces y herencia Una interfaz es un contrato, define qué métodos tendrá una clase y, por lo tanto, sus capacidades. Una interfaz no tiene una implementación, solo define lo que se necesita hacer. Un ejemplo en Java sería: interface Printalbe { public void print(); } La interfaz de Printalbe define un método llamado impresión, pero no proporciona su implementación (bastante extraño para Java). Cada clase que se declara a sí misma como implementing esta interfaz debe proporcionar una implementación al método de dibujo. Por https://riptutorial.com/es/home 6 ejemplo: class Person implements Printalbe { private String name; public Person(String name) { this.name = name; } public void print() { System.out.println(name); } } Si Person se declarara a sí mismo como implementable de Drawable pero no proporcionara una implementación para imprimir , habría un error de compilación y el programa no se compilaría. Herencia es un término que apunta a una clase que se extiende a otra clase. Por ejemplo, digamos que ahora tenemos una persona que tiene una edad. Una forma de implementar una persona así sería copiar la clase Persona y escribir una nueva clase llamada AgedPerson que tenga los mismos campos y métodos pero que tenga otra propiedad. Esto sería horrible ya que duplicamos todo nuestro código solo para agregar una característica simple a nuestra clase. Podemos usar la herencia para heredar de Person y así obtener todas sus características, y luego mejorarlas con nuestra nueva característica, así: class AgedPerson extends Person { private int age; public AgedPerson(String name, int age) { super(name); this.age = age; } public void print() { System.out.println("Name: " + name + ", age:" + age); } } Hay algunas cosas nuevas que están sucediendo: • Utilizamos la extends palabra guardada para indicar que estamos heredando de Person (y también su implementación en Imprimible , por lo que no necesitamos declarar la implementing Printable nuevamente). • Usamos la palabra super para llamar al constructor de Person . • Anulamos el método de impresión de Persona con uno nuevo. Esto se está volviendo bastante técnico en Java, así que no profundizaré más en este tema. Pero mencionaré que hay muchos casos extremos que deben aprenderse sobre la herencia y las interfaces antes de comenzar a usarlos. Por ejemplo, ¿qué métodos y funciones se heredan? ¿Qué sucede con los campos privados / públicos / protegidos cuando se hereda de una clase? y https://riptutorial.com/es/home 7 así. Clase abstracta Una clase abstracta es un término bastante avanzado en OOP que describe una combinación de ambas interfaces y herencia. Le permite escribir una clase que tiene métodos / funciones implementados y no implementados. En Java, esto se hace usando el abstract palabras clave y no lo explicaré más que un ejemplo rápido: abstract class AbstractIntStack { abstract public void push(int element); abstract public void pop(); abstract public int top(); final public void replaceTop(int element) { pop(); push(element); } } Nota: la palabra clave final indica que no puede anular este método cuando hereda de esta clase. Si una clase se declara definitiva, entonces ninguna clase puede heredarla. Lea Empezando con oop en línea: https://riptutorial.com/es/oop/topic/5081/empezando-con-oop https://riptutorial.com/es/home 8 Capítulo 2: Abstracción Examples Abstracción - Introducción La abstracción es uno de los conceptos principales en Programación Orientada a Objetos (OOP) . Este es el proceso de ocultar los detalles de la implementación para los forasteros y mostrar solo los detalles esenciales. En otras palabras, la abstracción es una técnica para organizar la complejidad de un programa. Hay dos tipos básicos de abstracción: 1. Control de abstracción Esto se hace utilizando sub-rutinas y flujo de control. Podemos llamar a otra función / método / rutina (sub-rutina) desde una función / método para hacer una tarea específica, donde esa sub-rutina es abstracta. 2. Abstracción de datos Esto se hace a través de varias estructuras de datos y sus implementaciones. Podemos crear nuestras propias estructuras de datos para almacenar nuestros datos, mientras mantenemos el resumen de la implementación. En OOP usamos una mezcla de control y abstracción de funciones. Modificadores de acceso Los modificadores de acceso se utilizan para controlar el acceso a un objeto oa una función / método. Esta es una parte principal del concepto de abstracción . Diferentes lenguajes de programación utilizan diferentes modificadores de acceso. Aquí hay unos ejemplos: • Java Java tiene 4 modificadores de acceso. 1. private : solo se puede acceder a estos atributos dentro de la clase. 2. protected : se puede acceder a estos atributos mediante subclases y clases del mismo paquete. 3. package : solo las clases dentro del mismo paquete pueden acceder a estos atributos. 4. public : todos los usuarios pueden acceder a estos atributos. • C ++ C ++ tiene 3 modificadores de acceso. https://riptutorial.com/es/home 9 1. private : solo se puede acceder a estos atributos dentro de la clase. 2. protected : estos atributos pueden ser accedidos por clases derivadas. 3. public : todos los usuarios pueden acceder a estos atributos. • DO# C # tiene 5 modificadores de acceso 1. private : solo se puede acceder a estos atributos dentro de la clase. 2. protected internal : se puede acceder a estos atributos mediante el mismo ensamblaje y las clases derivadas. 3. protected : estos atributos pueden ser accedidos por clases derivadas. 4. public internal : las clases pueden acceder a estos atributos dentro del mismo ensamblaje. 5. public : todos los usuarios pueden acceder a estos atributos. Lea Abstracción en línea: https://riptutorial.com/es/oop/topic/7324/abstraccion https://riptutorial.com/es/home 10 Capítulo 3: Clase Examples Introducción Clase es la pieza de código donde definimos los atributos y / o comportamientos de un objeto. Puede definir variables, constantes, métodos y constructores para el objeto, dentro de la clase. En otras palabras, la clase es el plano de un objeto. Veamos una clase de muestra en Java, que define un Coche (simple): public class Car { private Engine engine; private Body body; private Tire [] tire; private Interior interior; // Constructor public Car (Engine engine, Body body, Tire[] tires, Interior interior) { } // Another constructor public Car () { } public void drive(Direction d) { // Method to drive } public void start(Key key) { // Start } } Esto es solo por un ejemplo. Puede modelar objetos del mundo real como este, según sus necesidades. Lea Clase en línea: https://riptutorial.com/es/oop/topic/7374/clase https://riptutorial.com/es/home 11 Capítulo 4: Encapsulacion Examples Ocultación de información El estado de un objeto en un momento dado está representado por la información que contiene en ese punto. En un lenguaje OO, el estado se implementa como variables miembro. En un objeto adecuadamente diseñado, el estado solo puede cambiarse mediante llamadas a sus métodos y no mediante la manipulación directa de sus variables miembro. Esto se logra proporcionando métodos públicos que operan sobre los valores de las variables de miembros privados. La ocultación de información de esta manera se conoce como encapsulación . Por lo tanto, la encapsulación garantiza que la información privada no se expone y no se puede modificar, excepto a través de llamadas a los usuarios y métodos, respectivamente. En el siguiente ejemplo, no puedes hacer que un Animal deje de tener hambre cambiando el campo privado hungry ; en cambio, tienes que invocar el método eat() , que altera el estado del Animal al poner la bandera de hungry en false . public class Animal { private boolean hungry; public boolean isHungry() { return this.hungry; } public void eat() { this.hungry = false; } } Lea Encapsulacion en línea: https://riptutorial.com/es/oop/topic/5958/encapsulacion https://riptutorial.com/es/home 12 Capítulo 5: Herencia Observaciones Nota: la herencia multinivel está permitida en Java pero no la herencia múltiple. Obtenga más información en http://beginnersbook.com/2013/04/oops-concepts/ Examples Herencia - Definición La herencia es uno de los conceptos principales en la programación orientada a objetos (OOP) . Usando la herencia, podemos modelar un problema correctamente y podemos reducir el número de líneas que tenemos que escribir. Veamos la herencia usando un ejemplo popular. Considera que tienes que modelar el reino animal (Reino animal simplificado, por supuesto. Biólogos, perdóname) usando OOP. Hay muchas especies de animales, algunos tienen características únicas, mientras que otros comparten las mismas características. Hay una de las principales familias de animales. Digamos, Mammals , Reptiles . Entonces tenemos hijos de esas familias. Para un ejemplo, • • , Dog y Lion son los mamíferos. Cobra y el Python son reptiles. Cat Cada animal comparte algunas características básicas como eat , drink , move . Por lo tanto, podemos decir que podemos tener un padre llamado Animal del cual pueden heredar esas características básicas. Entonces esas familias también comparten algunas características. Por ejemplo, los reptiles usan el rastreo para moverse. Todos los mamíferos son fed milk en las primeras etapas de la vida. Luego hay algunas características únicas para cada animal. Considere si vamos a crear estas especies animales por separado. Tenemos que escribir el mismo código una y otra vez en cada especie animal. En lugar de eso, usamos la herencia. Podemos modelar el Reino Animal de la siguiente manera: • Podemos tener un objeto primario llamado Animal , que tiene características básicas de todos los animales. • Mammal y Reptile (por supuesto, las otras familias de animales también) se opone a los objetos con sus características comunes mientras que hereda las características básicas del objeto principal, Animal . • Objetos de especies animales: el Cat y el Dog heredan del objeto Mammal , Cobra y Python heredan del objeto Reptile , y así sucesivamente. https://riptutorial.com/es/home 13 De esta forma podemos reducir el código que escribimos, ya que no necesitamos definir las características básicas de los Animales en cada especie animal, ya que podemos definirlos en el objeto Animal y luego heredarlos. Lo mismo ocurre con las familias de animales. Ejemplo de herencia - Considera debajo de dos clases Clase de profesor class Teacher { private String name; private double salary; private String subject; public Teacher (String tname) { name = tname; } public String getName() { return name; } private double getSalary() { return salary; } private String getSubject() { return subject; } } Clase OfficeStaff: class OfficeStaff{ private String name; private double salary; private String dept; public OfficeStaff (String sname) name = sname; } public String getName() { return name; } private double getSalary() { return salary; } private String getDept () { return dept; } } { 1. Ambas clases comparten algunas propiedades y métodos comunes. Así se repite el código. 2. Creando una clase que contiene los métodos y propiedades comunes. 3. Las clases Teacher y OfficeStaff pueden heredar todas las propiedades y métodos comunes de la clase Employee a continuación. Clase de empleado: class Employee{ private String name; https://riptutorial.com/es/home 14 private double salary; public Employee(String ename){ name=ename; } public String getName(){ return name; } private double getSalary(){ return salary; } } 4. Agregue métodos y propiedades individuales. Una vez que hayamos creado una súper clase que define los atributos comunes a un conjunto de objetos, puede usarse para crear cualquier número de subclases más específicas. 5. Cualquier clase similar como Ingeniero, Principal se puede generar como subclases de la clase Empleado. 6. La clase padre se denomina súper clase y la clase heredada es la subclase 7. Una subclase es la versión especializada de una súper clase: hereda todas las variables de instancia y los métodos definidos por la superclase y agrega sus propios elementos únicos. 8. Aunque una subclase incluye a todos los miembros de su súper clase, no puede acceder a aquellos miembros de la súper clase que han sido declarados como privados. 9. Una variable de referencia de una súper clase puede asignarse a una referencia a cualquier subclase derivada de esa súper clase, es decir, Empleado emp = nuevo Profesor (); Lea Herencia en línea: https://riptutorial.com/es/oop/topic/7321/herencia https://riptutorial.com/es/home 15 Capítulo 6: Objeto Examples Introducción Objeto es el módulo base en la Programación Orientada a Objetos (OOP) . Un objeto puede ser una variable, una estructura de datos (como una matriz, un mapa, etc.) o incluso una función o un método. En OOP, modelamos objetos del mundo real como animales, vehículos, etc. Un objeto se puede definir en una clase, que se puede definir como el plano del objeto. Luego podemos crear instancias de esa clase, que llamamos objetos. Podemos usar estos objetos, sus métodos y variables en nuestro código después. Lea Objeto en línea: https://riptutorial.com/es/oop/topic/7377/objeto https://riptutorial.com/es/home 16 Capítulo 7: Polimorfismo Examples Introducción El polimorfismo es uno de los conceptos básicos en OOP (Programación Orientada a Objetos) . La idea principal del polimorfismo es que un objeto tiene la capacidad de adoptar diferentes formas. Para lograr eso (polimorfismo), tenemos dos enfoques principales. 1. Método de sobrecarga • Ocurre cuando hay dos o más métodos con el mismo nombre, con diferentes parámetros de entrada. El tipo de retorno debe ser el mismo para todos los métodos con el mismo nombre 2. Método de anulación • Ocurre cuando el objeto hijo usa la misma definición de método (el mismo nombre con los mismos parámetros), pero tienen implementaciones diferentes. Usando estos dos enfoques, podemos usar el mismo método / función para comportarnos de manera diferente. Veamos más detalles sobre esto en los siguientes ejemplos. Método de sobrecarga La sobrecarga de métodos es la forma de usar el polimorfismo dentro de una clase. Podemos tener dos o más métodos dentro de la misma clase, con diferentes parámetros de entrada. La diferencia de los parámetros de entrada puede ser: • Numero de parametros • Tipo de parámetros (tipo de datos) • Orden de los parametros Echemos un vistazo a ellos por separado (Estos ejemplos en java, ya que estoy más familiarizado con eso, lo siento): 1. Número de parámetros public class Mathematics { public int add (int a, int b) { return (a + b); } public int add (int a, int b, int c) { return (a + b + c); } https://riptutorial.com/es/home 17 public int add (int a, int b, int c, int c) { return (a + b + c + d); } } Mire con cuidado, puede ver que el tipo de retorno del método es el mismo: int , pero por lo tanto, estos métodos tienen un número diferente de entradas. Esto se llama como método de carga con diferente número de parámetros. PD: Este es solo un ejemplo , no es necesario definir funciones de adición como esta. 2. Tipo de parametros public class Mathematics { public void display (int a) { System.out.println("" + a); } public void display (double a) { System.out.println("" + a); } public void display (float a) { System.out.println("" + a); } } Tenga en cuenta que todos los métodos tienen el mismo nombre y el mismo tipo de retorno, mientras que tienen diferentes tipos de datos de entrada. PS: Este ejemplo es solo para explicar el propósito solamente. 3. Orden de los parametros public class Mathematics { public void display (int a, double b) { System.out.println("Numbers are " + a + " and " + b); } public void display (double a, int b) { System.out.println("Numbers are " + a + " and " + b); } } PS: Este ejemplo es también para explicar el propósito solamente. Método Anulando La anulación del método es la forma de usar el polimorfismo entre clases. Si una clase se hereda de otra, la primera (subclase) puede anular los métodos de la última (super clase) y cambiar la implementación. https://riptutorial.com/es/home 18 esto se usa cuando la superclase define la implementación más general del método, mientras que la subclase usa una más específica. Considere el siguiente ejemplo: Tenemos una clase para mamíferos: class Mammal { void whoIam () { System.out.println("I am a Mammal"); } } Luego tenemos una clase para perro, que es un mamífero: class Dog extends Mammal { @Override void whoIam () { super.whoIam(); System.out.println("I am a Dog!"); } } En este ejemplo, definimos el método whoIam() en la clase de Mammal , donde el mamífero dice que es un mamífero. Pero este es un término general, ya que hay muchos mamíferos por ahí. Entonces podemos heredar la clase de Dog clase de Mammal , ya que el perro es un mamífero. Pero, para ser más específicos, el perro es un perro y un mamífero. Por lo tanto, el perro debería decir, I am a Mammal y también I am a Dog . De ahí que puede anular el whoIam() método en el súper clase ( Mammal clase, que es) de la clase sub (el Dog clase). También podemos llamar al método de la súper clase usando super.whoIam() en Java. Entonces, el Dog se comportará como un perro, mientras que también se comportará como un mamífero. Lea Polimorfismo en línea: https://riptutorial.com/es/oop/topic/7323/polimorfismo https://riptutorial.com/es/home 19 Capítulo 8: Problema del diamante Examples Problema del diamante - Ejemplo El problema del diamante es un problema común que se presenta en la programación orientada a objetos, mientras se usa multiple-inheritance . Considere el caso donde la class C , se hereda de la class A y la class la class A como la class B tienen un método llamado foo() . B Supongamos que tanto Luego, cuando estamos llamando al método foo() , el compilador no puede identificar el método exacto que estamos tratando de usar • • de la class foo() de la class foo() A B Esto se llama básicamente el problema del diamante. Hay algunas variantes de este problema. Para evitar esto, hay múltiples enfoques. Java no permite la herencia múltiple. De ahí que se evite el problema. Pero C ++ está permitiendo la herencia múltiple, por lo tanto, debe tener cuidado de usar la herencia múltiple. Lea Problema del diamante en línea: https://riptutorial.com/es/oop/topic/7319/problema-deldiamante https://riptutorial.com/es/home 20 Creditos S. No Capítulos Contributors 1 Empezando con oop Alon Alexander, Community, James, Thisaru Guruge 2 Abstracción davioooh, Thisaru Guruge 3 Clase Thisaru Guruge 4 Encapsulacion davioooh, jeyoung 5 Herencia SRENG Khorn, Thisaru Guruge 6 Objeto Thisaru Guruge 7 Polimorfismo Fantasy Pollock, murthy, Thisaru Guruge 8 Problema del diamante Thisaru Guruge https://riptutorial.com/es/home 21