Programación Orientada a Objetos en Java: Inicio para principiantes

Go to Homepage

Comenzando con Programación Orientada a Objetos

La programación orientada a objetos es un paradigma muy popular y ampliamente utilizado en el mundo del desarrollo de software. Es probable que hayas escuchado de este término mientras aprendes a programar, especialmente si estas empezando en el mundo de la programación con el lenguaje de programación Java. En este artículo, te brindaremos una guía de los conceptos básicos de la programación orientada a objetos en Java.

Las principales características de la programación orientada a objetos son: clases, herencia, polimorfismo y encapsulamiento. Todos estos conceptos se basan en el concepto fundamental de objetos, que son representaciones de cosas o procesos del mundo real.

Clases

Una clase es una plantilla que define las propiedades y los comportamientos de un objeto. Por ejemplo, si utilizamos la analogía de un carro, podríamos tener una clase Carro que defina propiedades como marca, modelo y color, y comportamientos como arrancar y detenerse.

Herencia

La herencia permite que una clase (conocida como clase hija) herede propiedades y comportamientos de otra clase (conocida como clase padre). Esto facilita la reutilización del código y permite que las clases se organizan en jerarquías. Por ejemplo, una clase Sedan podría heredar propiedades de la clase Carro y tener sus propias propiedades únicas como capacidad, consumo de combustible, entre otros.

Polimorfismo

El polimorfismo se refiere a la capacidad de un objeto para tomar muchas formas. En términos de programación orientada a objetos, esto significa que una clase hija puede tener un comportamiento diferente al de su clase padre. Por ejemplo, una clase Bici podría tener una comportamiento de avanzarRuedaPorRueda(), mientras que una clase Moto tiene una comportamiento de avanzarConMotor(). Ambas clases pueden tener un método avanzar() pero con diferentes comportamientos.

Encapsulamiento

El encapsulamiento se refiere al concepto de ocultar o limitar la acceso a las propiedades y comportamientos de un objeto. Esto se hace para proteger el objeto y asegurar que su estado interno sea coherente. Por ejemplo, una propiedad fuelLevel solo debe cambiar mediante un método cambiarNivelCombustible() y no debe ser accesible desde fuera del objeto.

Estos son solo algunos de los conceptos básicos de la programación orientada a objetos en Java. Si eres un principiante en la programación, puede resultar un poco abrumador, pero no desesperes, ¡todos los programadores han pasado por esto! Dedica tiempo a entender y practicar los conceptos básicos antes de avanzar a conceptos más avanzados.

Un ejemplo de código de una clase en Java puede ser el siguiente:

public class Carro {
    private String marca;
    private String modelo;
    private String color;

    public void arrancar() {
        //...
    }

    public void detenerse() {
        //...
    }
}

La programación orientada a objetos es uno de los conceptos más importantes para aprender en la programación, y Java es uno de los lenguajes de programación más utilizados y populares en este paradigma. Es esencial entender los conceptos básicos como clases, herencias, polimorfismo y encapsulamiento para poder desarrollar programas exitosos que se puedan mantener y evolucionar.

¿Qué son los objetos en Java?

En programación orientada a objetos en Java, los objetos son piezas fundamentales. Un objeto es una instancia de una clase. Una clase en Java es un modelo o plantilla que define las propiedades y el comportamiento de un objeto. Cada objeto tiene su propia identidad, estado y comportamiento, y se crea a partir de una clase.

El estado de un objeto se refiere a sus variables o atributos, mientras que el comportamiento se refiere a los métodos definidos en su clase. Por ejemplo, un objeto de la clase Person puede tener atributos como name, age y gender, y métodos como speak(), walk(), y eat().

Cuando creamos una instancia de una clase, estamos creando un objeto con sus propias características. Por ejemplo, podemos crear una instancia de la clase Person llamada John con atributos name = "John", age = 30, y gender = "Male". Podemos entonces llamar al método speak() de John para que hable.

// Creamos la clase Person
public class Person {
    String name;
    int age;
    String gender;

    // Método para que la persona hable
    public void speak() {
        System.out.println("Hello, my name is " + name);
    }
}

// Creamos una instancia de la clase Person
Person John = new Person();
John.name = "John";
John.age = 30;
John.gender = "Male";

// Llamamos al método speak() de John
John.speak();

En Java, los objetos también pueden heredar variables y métodos de otras clases a través de la herencia. Esto significa que podemos crear una nueva clase basada en una clase existente y agregarle o modificarle funcionalidades. Por ejemplo, si creamos una clase Student que hereda de la clase Person, podemos agregarle atributos como studentId y métodos como study().

// Creamos la clase Student que hereda de Person
public class Student extends Person {
    int studentId;

    // Método para que el estudiante estudie
    public void study() {
        System.out.println(name + " is studying...");
    }
}

// Creamos una instancia de la clase Student
Student Alice = new Student();
Alice.name = "Alice";
Alice.age = 20;
Alice.gender = "Female";
Alice.studentId = 123;

// Llamamos al método speak() y study() de Alice
Alice.speak();
Alice.study();

Además de la herencia, otro concepto importante en programación orientada a objetos es el polimorfismo, que significa que un objeto puede tomar muchas formas diferentes. Por ejemplo, un mismo método puede comportarse de manera diferente en distintas clases.

El encapsulamiento es otro concepto clave en la programación orientada a objetos en Java. Se trata de ocultar los detalles internos de una clase y exponer solo los que son necesarios para interactuar con ella. Esto se logra mediante el uso de métodos y variables privadas, protegidas y públicas.

Los objetos son una parte fundamental de la programación orientada a objetos en Java. Son instancias de clases que tienen su propio estado y comportamiento. Los objetos pueden heredar de otras clases, tomar muchas formas diferentes y estar encapsulados. Al conocer estos conceptos, podemos crear programas más complejos y eficientes en Java.

Cómo crear clases y objetos en Java

En la programación orientada a objetos en Java, las clases y objetos son los elementos principales que permiten desarrollar aplicaciones. Las clases son la plantilla o estructura que define un objeto y sus propiedades, mientras que los objetos son instancias específicas de esas clases.

Para crear una clase en Java, debemos utilizar la siguiente estructura:

public class MiClase {
    // Declaración de propiedades
    // Declaración de métodos
}

La palabra clave public indica que la clase es accesible desde cualquier parte del programa. Después del public va la palabra class, seguida del nombre de la clase en CamelCase. Dentro de las llaves { } definimos las propiedades y métodos de la clase.

Las propiedades son variables que almacenan información dentro de una clase. Estas variables se definen con su tipo de dato y un nombre, y pueden ser públicas o privadas, según queramos que estén disponibles para otras clases.

public class MiClase {
    public int edad;
    private String nombre;
}

En este ejemplo, edad es una propiedad pública de tipo entero, y nombre es una propiedad privada de tipo cadena.

Los métodos son funciones que realizan acciones dentro de una clase. Estos métodos pueden ser públicos o privados, dependiendo de si queremos que estén disponibles para otras clases.

public class MiClase {
    public void saludar() {
        System.out.println("Hola, soy " + nombre);
    }
    private void despedir() {
        System.out.println("Adiós");
    }
}

En este caso, saludar() es un método público que imprime un saludo junto al nombre de la instancia de la clase, mientras que despedir() es un método privado que simplemente imprime “Adiós”.

Para crear un objeto a partir de una clase, utilizamos la siguiente estructura:

MiClase objeto = new MiClase();

Esto crea una instancia de la clase MiClase y la asigna a la variable objeto.

Una de las ventajas de la programación orientada a objetos es la herencia, que permite crear nuevas clases basadas en otras clases existentes. Para hacer una clase que herede de otra clase, utilizamos la siguiente estructura:

public class OtraClase extends MiClase {
    // Declaración de nuevas propiedades y métodos
}

En este ejemplo, OtraClase hereda todas las propiedades y métodos públicos de MiClase.

Otra característica importante de la programación orientada a objetos es el polimorfismo, que permite a los objetos de distintas clases responder al mismo método de forma diferente.

Por último, el encapsulamiento es un concepto que permite proteger las propiedades y métodos de una clase para que no sean accesibles desde fuera de la clase.

En definitiva, las clases y objetos son los elementos fundamentales de la programación orientada a objetos en Java. Con ellos podemos modelar la estructura y la funcionalidad de nuestras aplicaciones de forma modular y reutilizable.

Encapsulamiento y sus beneficios en la programación

El encapsulamiento es uno de los conceptos fundamentales en la programación orientada a objetos en Java y en otros lenguajes de programación similares. En resumen, encapsulamiento significa que los datos dentro de una clase deben estar protegidos de los cambios externos y solo deben ser accesibles a través de métodos específicos.

El encapsulamiento ayuda a disminuir la complejidad y aumentar la modularidad del código, lo que a su vez hace que sea más fácil de entender, depurar y mantener. Además, la encapsulación también ayuda a prevenir errores al reducir la cantidad de puntos de acceso a los datos de una clase, lo que significa que es menos probable que se produzcan cambios accidentales o no intencionales.

En el siguiente ejemplo, se muestra cómo se puede usar la encapsulación en una clase de juguete llamada Perro:

public class Perro {
    private String nombre;
    private int edad;

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public int getEdad() {
        return edad;
    }

    public void setEdad(int edad) {
        this.edad = edad;
    }
}

En este ejemplo, las variables nombre y edad están marcadas como private, lo que significa que solo se pueden acceder a ellas dentro de la clase. Sin embargo, la clase también tiene métodos get y set para cada una de estas variables, lo que permite a las personas fuera de la clase obtener y actualizar los valores. Estos métodos son públicos, lo que significa que se pueden acceder a ellos desde cualquier parte del código que tenga acceso a un objeto Perro.

El encapsulamiento también se puede utilizar en la herencia y el polimorfismo. Por ejemplo, se pueden crear clases secundarias que hereden los atributos y métodos de una clase principal, y luego modificar o añadir comportamientos adicionales según sea necesario. El polimorfismo también permite a los programadores escribir código que se puede utilizar con diferentes clases, lo que aumenta la reutilización y reduce la duplicación de código.

El encapsulamiento es un concepto esencial en la programación orientada a objetos en Java y otros lenguajes de programación similares. Ayuda a proteger los datos de la clase de cambios no deseados, lo que a su vez aumenta la modularidad y reduce la complejidad. También se puede utilizar junto con la herencia y el polimorfismo para crear jerarquías de clases más complejas y flexibles.

Herencia y Polimorfismo en Java

En la programación orientada a objetos en Java, dos de los conceptos más importantes que debemos entender son la herencia y el polimorfismo. Ambos nos ayudan a crear código más eficiente y mantenible al aprovechar las abstracciones y características comunes entre objetos.

La herencia se refiere a la capacidad de una clase de heredar propiedades y métodos de otra clase. Por ejemplo, si tenemos una clase Animal con propiedades y métodos comunes a todos los animales, podemos crear una clase Perro que extienda Animal y herede esas propiedades y métodos. Esto significa que no tenemos que repetir código y podemos crear clases más específicas con menos esfuerzo.

En Java, la herencia se indica usando la palabra clave extends. Por ejemplo, si queremos que la clase Perro extienda Animal, escribimos:

public class Perro extends Animal {
  // propiedades y métodos específicos de los perros
}

Las propiedades y métodos en la clase Animal se convierten en propiedades y métodos de la clase Perro, lo que significa que podemos acceder a ellos directamente desde la clase Perro. Por ejemplo, si la clase Animal tiene un método llamado moverse(), podemos llamarlo desde la clase Perro de la siguiente manera:

public class Perro extends Animal {
  public void moverse() {
    super.moverse(); // llamamos al método moverse() de la clase Animal
    System.out.println("El perro corre");
  }
}

Otros animales como los gatos o los pájaros pueden extender también Animal y aprovechar sus propiedades y métodos sin tener que escribir el código necesario.

El polimorfismo se refiere a la capacidad de un objeto de tomar diferentes formas. En el contexto de la programación orientada a objetos, esto significa que diferentes objetos que comparten una clase base pueden ser tratados de manera intercambiable.

Por ejemplo, si tenemos tres clases que extienden Animal: Perro, Gato, y Pajaro, podemos crear un arreglo de Animal y llenarlo con instancias de cualquiera de esas tres clases. Aunque los objetos en el arreglo sean distintos, podemos tratarlos de manera intercambiable porque tienen una base común: la clase Animal.

Animal[] animales = new Animal[3];
animales[0] = new Perro();
animales[1] = new Gato();
animales[2] = new Pajaro();

for (Animal animal : animales) {
  animal.moverse();
}

El polimorfismo se basa en la idea de que cuanto más general sea la descripción de un objeto, más tipos de objetos pueden ser descritos por ella. Al crear clases base y extenderlas con clases más específicas, podemos utilizar el polimorfismo para crear código más flexible y reutilizable.

La herencia y el polimorfismo son conceptos clave en la programación orientada a objetos en Java. Nos permiten crear abstracciones y aprovechar las propiedades y métodos comunes entre objetos para crear código más eficiente, y nos proporcionan una manera poderosa para tratar objetos de manera intercambiable.

Métodos y Constructores en las Clases

En la programación orientada a objetos (POO) en Java, las clases juegan un papel fundamental. Dentro de ellas, se definen métodos y constructores que dan forma a la funcionalidad de los objetos que se generen a partir de ellas.

Los métodos son bloques de código que definen una acción específica de la clase. En Java, los métodos tienen un nombre, pueden recibir parámetros y pueden retornar valores. Por ejemplo, un método en una clase Carro podría ser “acelerar” y tomar como parámetro la cantidad de kilómetros por hora que se desea aumentar en la velocidad actual del automóvil. El método podría retornar la velocidad final del vehículo después de la aceleración.

Por otro lado, los constructores son métodos especiales que se encargan de inicializar los objetos. En ellos se definen los valores iniciales de las variables que conforman el objeto. En Java, el constructor tiene el mismo nombre que la clase y no retorna ningún valor.

Veamos un ejemplo de cómo se definen un método y un constructor en una clase en Java:

public class Carro {
    // Variables de instancia
    String marca;
    String modelo;
    int ano;

    // Constructor
    public Carro(String marca, String modelo, int ano) {
        this.marca = marca;
        this.modelo = modelo;
        this.ano = ano;
    }

    // Método
    public void acelerar(int kmh) {
        int velocidadActual = ... // Código para obtener velocidad actual
        int velocidadFinal = velocidadActual + kmh; // Cálculo de velocidad final
        ... // Código para ajustar la velocidad del carro
    }
}

En este ejemplo se define una clase “Carro” que tiene tres variables de instancia: “marca”, “modelo” y “año”. Además, se definen un constructor que recibe estos tres valores como parámetros y un método “acelerar” que toma como parámetro la cantidad de kilómetros por hora que se desea aumentar en la velocidad actual del carro.

Es importante destacar que las clases en POO también permiten el uso de conceptos como herencia, polimorfismo y encapsulamiento para lograr una mayor modularidad del código y permitir una mejor organización.

Los métodos y constructores son elementos esenciales en la programación orientada a objetos en Java. A través de ellos, se puede dar funcionalidad a las clases y permitir la creación de objetos que cumplan con dicha funcionalidad.

Clases Abstractas y Interfaces

Las clases abstractas y las interfaces son dos conceptos fundamentales en la programación orientada a objetos en Java. Para los principiantes, puede ser difícil entender la diferencia entre ambas y su uso adecuado.

una clase abstracta es aquella que no tiene una implementación completa y requiere que sus hijos la completen mediante la implementación de sus métodos abstractos. Por otro lado, una interfaz es un conjunto de métodos sin implementación que debe implementarse completamente por cualquier clase o interfaz que lo implemente.

Las clases abstractas se utilizan a menudo para definir comportamientos comunes entre clases hijas, mientras que las interfaces pueden usarse para definir comportamientos comunes entre clases que no tienen una relación jerárquica. Además, una clase puede extender una sola clase abstracta, pero puede implementar múltiples interfaces.

El uso de clases abstractas puede ser complicado en algunos casos porque se debe tener cuidado al definir los métodos abstractos y cómo se implementan en las clases hijas. Por otro lado, el uso de interfaces puede ayudar a mantener un acoplamiento débil entre las clases, lo que significa que los cambios en una clase no afectan a las otras clases que dependen de ella.

Aquí hay un ejemplo de clase abstracta:

public abstract class Vehiculo {
    private int velocidad;

    public Vehiculo(int velocidad) {
        this.velocidad = velocidad;
    }

    public abstract void moverse();

    public int getVelocidad() {
        return velocidad;
    }

    public void setVelocidad(int velocidad) {
        this.velocidad = velocidad;
    }
}

La clase abstracta Vehiculo tiene un constructor que inicializa la velocidad y dos métodos, moverse() y getVelocidad(), pero el método moverse() es abstracto y se define en las clases hijas.

Aquí hay un ejemplo de interfaz:

public interface Animal {
    public void hacerSonido();
    public void moverse();
}

La interfaz Animal tiene dos métodos abstractos hacerSonido() y moverse(), que deben ser implementados por cualquier clase que lo implemente.

El uso adecuado de clases abstractas e interfaces puede ayudar a diseñar una aplicación mejor estructurada y modular. Las clases abstractas pueden definir comportamientos comunes entre clases hijas y las interfaces pueden definir comportamientos comunes entre clases que no tienen una relación jerárquica. Es importante tener en cuenta los pros y los contras de cada uno y utilizarlos de manera adecuada en el diseño de la aplicación.

Manejo de Excepciones en Java

El manejo de excepciones en Java es una parte fundamental de la programación orientada a objetos. Para los principiantes en Java, puede ser un tanto complicado entender cómo funciona el manejo de excepciones, pero es esencial para escribir un código robusto y confiable.

En Java, una excepción es un evento que ocurre durante la ejecución de un programa que interrumpe el flujo normal del programa. Cuando una excepción es lanzada, el programa deja de ejecutarse y el control se transfiere a un manejo de excepción. El manejo de excepciones permite al programador manejar los errores de una manera estructurada y segura.

En Java, las excepciones se manejan con bloques try-catch. El bloque try encierra el código que puede producir una excepción, mientras que el bloque catch maneja la excepción en caso de que se produzca. Aquí hay un ejemplo de código que demuestra cómo utilizar un bloque try-catch:

try {
  // Código que puede producir una excepción
} catch (ExceptionTipo1 e1) {
  // Manejo de la excepción Tipo 1
} catch (ExceptionTipo2 e2) {
  // Manejo de la excepción Tipo 2
} catch (Exception e) {
  // Manejo de cualquier otra excepción
}

En el ejemplo anterior, hay tres bloques catch que manejan diferentes tipos de excepciones. El bloque catch con el parámetro Exception maneja cualquier otra excepción que no esté definida en los bloques catch anteriores.

Es importante tener en cuenta que cuando una excepción es lanzada, el control se transfiere automáticamente al bloque catch correspondiente. Esto significa que el código que sigue al bloque catch no se ejecutará si se lanza una excepción.

Además de manejar excepciones con bloques try-catch, también es posible lanzar excepciones de manera intencional con la palabra clave throw. Aquí hay un ejemplo de código que muestra cómo lanzar una excepción:

public int dividir(int a, int b) throws ArithmeticException {
  if (b == 0) {
    throw new ArithmeticException("No se puede dividir por cero.");
  }
  return a / b;
}

En el ejemplo anterior, se lanza una excepción de tipo ArithmeticException si el segundo parámetro es 0. La palabra clave throws en la firma del método indica que el método puede lanzar una excepción.

El manejo de excepciones es una parte importante de la programación orientada a objetos en Java. Con bloques try-catch y la palabra clave throw, los programadores pueden manejar las excepciones de manera estructurada y segura. Es fundamental entender cómo funciona el manejo de excepciones para escribir un código robusto y confiable.

Colecciones en Java y su uso en POO

En POO, las colecciones son fundamentales para manejar grandes cantidades de objetos de manera eficiente. En Java, las colecciones más comunes son:

Colección Descripción
ArrayList Una lista de objetos que se pueden acceder mediante su índice.
LinkedList Similar a ArrayList, pero con una estructura de lista enlazada más eficiente para agregar y eliminar elementos.
HashSet Una colección que no permite duplicados y no tiene un orden definido.
TreeSet Similar a HashSet, pero ordenado en orden ascendente.
HashMap Una colección que almacena pares clave-valor, donde cada clave es única y se utiliza para acceder al valor correspondiente.
TreeMap Similar a HashMap, pero ordenado por la clave en orden ascendente.

Para utilizar estas colecciones, primero es necesario importar la clase correspondiente en nuestro archivo de código. Por ejemplo, para utilizar ArrayList:

import java.util.ArrayList;

public class Ejemplo {
  public static void main(String[] args) {
    ArrayList<String> miLista = new ArrayList<>();
    miLista.add("Hola");
    miLista.add("mundo");
    System.out.println(miLista);
  }
}

La salida sería: [Hola, mundo]

En este ejemplo, hemos creado un ArrayList de tipo String (ArrayList<String>) y luego agregamos dos elementos utilizando el método add(). Finalmente, imprimimos la lista completa utilizando el método toString() que se llama implícitamente al imprimir el objeto.

Las clases de colecciones en Java tienen una gran cantidad de métodos disponibles para añadir, eliminar y acceder a elementos. Además, también hay métodos para ordenar, buscar y filtrar elementos de la colección.

Por ejemplo, podemos ordenar un ArrayList utilizando el método sort():

import java.util.ArrayList;
import java.util.Collections;

public class Ejemplo {
  public static void main(String[] args) {
    ArrayList<String> miLista = new ArrayList<>();
    miLista.add("Delta");
    miLista.add("Charlie");
    miLista.add("Alpha");
    miLista.add("Bravo");
    System.out.println(miLista);
    Collections.sort(miLista);
    System.out.println(miLista);
  }
}

La salida sería:

[Delta, Charlie, Alpha, Bravo]
[Alpha, Bravo, Charlie, Delta]

En este ejemplo, primero agregamos cuatro elementos a nuestro ArrayList miLista. Luego, imprimimos la lista en su orden original y posteriormente utilizamos el método sort() de la clase Collections para ordenar la lista alfabéticamente en orden ascendente.

Las colecciones en Java son unas herramientas poderosas en programación orientada a objetos que facilitan el manejo de objetos en grandes cantidades. Al utilizarlas, los programadores pueden escribir código más eficiente y legible.

El futuro de la Programación Orientada a Objetos en Java

La programación orientada a objetos ha demostrado ser una de las metodologías más eficientes y flexibles en el desarrollo de software. Java, en particular, ha sido una de las tecnologías más populares para implementar esta metodología. A medida que evoluciona la industria del software, es importante conocer las tendencias futuras y cómo se relacionan con la programación orientada a objetos en Java.

Una de las tendencias emergentes en la programación orientada a objetos en Java es el aumento del uso de clases anónimas. Este tipo de clase es útil para implementar interfaces y clases abstractas de manera clara y concisa en entornos específicos. Las clases anónimas también son beneficiosas porque pueden ser modificadas sin afectar otras partes del código.

Otra tendencia relevante es el aumento del uso de generics. Este concepto permite declarar tipos de datos específicos en tiempo de compilación. Una vez instanciados los tipos de datos, Java no permite la adición de elementos incompatibles en las colecciones. Esto reduce los errores y aumenta la flexibilidad del código.

La herencia sigue siendo una característica clave de la programación orientada a objetos en Java, pero ahora se está utilizando más el concepto de composición de objetos. La composición es una alternativa a la herencia que permite crear objetos complejos a partir de objetos más simples. En lugar de extender una clase, se crean objetos que se comunican entre sí. Esto hace que los objetos sean más flexibles y fáciles de mantener.

Otro concepto importante es el polimorfismo. El polimorfismo es la capacidad de los objetos de responder a diferentes mensajes de la misma manera. Una aplicación del polimorfismo es el uso de interfaces. Las interfaces describen un conjunto de métodos que una clase debe implementar. Esto permite que una clase se comporte de diferentes maneras en función del contexto.

El encapsulamiento sigue siendo una práctica clave en la programación orientada a objetos en Java. El encapsulamiento se refiere a la ocultación de la complejidad interna de un objeto detrás de una interfaz pública simple. Esto permite cambios internos sin afectar a las partes del código que interactúan con el objeto.

El futuro de la programación orientada a objetos en Java sigue siendo brillante debido a su flexibilidad y eficiencia en el desarrollo de software. Es importante seguir aprendiendo los fundamentos de la programación orientada a objetos, entender las tendencias emergentes y aplicar estas técnicas para garantizar que el código siga siendo fácil de mantener y escalable.

El futuro de la programación orientada a objetos en Java es prometedor. Las tendencias emergentes, como el aumento del uso de clases anónimas y la composición de objetos, están mejorando la eficiencia y flexibilidad del código. Es importante seguir aprendiendo y aplicando estos conceptos para mantenerse actualizado en la industria del software.

Otros Artículos