# Javascript : Programación Orientada a Objetos

# Table of Contents
1. [El paradigma de la programación orientada a objetos](#el-paradigma-de-la-programación-orientada-a-objetos)
2. [Entendiendo qué es una clase ](#2-entendiendo-que-es-una-clase )
3. [Comportamiento de las clases : métodos](#)

## 1. El paradigma de la programación orientada a objetos
Cuando desarrollamos aplicaciones o programas, * transformamos un modelo del mundo real al mundo digital*. En el mundo real interactuamos con seres vivos y cosas inanimadas. 
Cada uno de ellos tiene características y comportamientos que lo definen y que nos permite entender como interactúan entre sí.
Por ello, se definió el paradigma de la** POO** (Programación Orientada a Objetos) , en donde realizamos una **abstracción** del mundo real y lo convertiremos en un **modelo de programación**.

## 2. Entendiendo qué es una clase 

Primero, deseamos crear una **clase** Cliente(que es un molde con caracteríticas muy generales) con sus propias características/**atributos** y propios **métodos**(funciones) e **instanciamos** generando nuevos **objetos**  .

Imaginemos tenemos una base de datos de un banco super genial con clientes siniguales, entonces deseamos gestionar las cuentas corrientes de los usuarios, colocar sus datos , reutilizar codigo y almacenarlos usando buenas prácticas.

Normalmente creariamos variables así:
```
const  nombreCliente = "Tyrone Backyardigan";
const  dniCliente = 12134;
```

Sin embargo, con *clases e instancias*, seria mucho más eficiente almacenar los datos así :

```
class Cliente {
  nombreCliente;
  dniCliente;
  nroCuenta;
  saldoCuenta;
  
}

//Ahora, aquí instanciamos :
const cliente1 = new Cliente();

cliente1.nombreCliente = "Tyrone Backyardigan";
cliente1.dniCliente = 12134;
cliente1.nroCuenta = 234567890;
cliente1.saldoCuenta = 500;

const cliente2 = new Cliente();
cliente2.nombreCliente = "Winnie Pooh";
cliente2.dniCliente = 23467;
cliente2.nroCuenta = 13454640;
cliente2.saldoCuenta = 8000;

console.log(cliente2);

``` 
Imprime en consola :

```
 [object Object]
 {
    "nombreCliente" = "Winnie Pooh",
    "dniCliente" = 23467,
    "nroCuente" = 12354640,
    "saldoCuenta" = 8000
}
``` 
Las clases definen una forma de organizar datos repetibles y, por eso, debemos usarlas para evitar tener que repetir líneas de código que hacen referencia a la misma información.

*Lo que aprendimos aquí:*

* Creación de clases
* Qué son los atributos/propiedades de una clase
* Instancia/Objeto de una clase
* Palabras reservadas **class** y **new**

## 3. Comportamiento de las clases (métodos)
**Encapsulamiento : **
Como vimos en la anterior parte, determinamos todos los atributos en una sola clase; sin embargo, no es tan eficiente si deseásemos hacer transferencias bancarias internas y externas. Podríamos optimizarlo mejor separándolos en 2 clases, una llamada _clase Cliente_ y otra llamada _clase CuentaCorriente_, así , podemos crear diferentes métodos para cada clase y más específicos. A este proceso se le denomina *encapsulamiento*

**This : **
Imagina que Tyrone ganó una rifa de 300 dólares, y desea guardarlo en su cuenta. Le creamos un método que define ese comportamiento: _depósitoEnCuenta(valor)_, el valor que se agregará.
De la misma manera si Tyrone desea unos nuevos audífonos, entonces retirará de su cuenta unos 20 dólares, crearemos para ello el método _retiroEnCuenta(valor)_. 
 
✔ El argumento seria el valor agregado o disminuido. El parámetro sería la variable 'valor' , lo cual al usar el método, retornaría un nuevo valor.
✔ Un método puede recibir cualquier cantidad de parámetros : Esa es la forma de pasarle información para que podamos reutilizar su funcionalidad en diferentes escenarios.
✔ Un método define el **comportamiento** o la forma de realizar algo : Ese es el objetivo de los métodos, definir qué acciones puede ejecutar un objeto. El comportamiento es implementado dentro del método.

**This** representa el valor actual que la máquina conserva y almacena. Por defecto, siempre será su valor inicial. Luego, tomaría el valor del nuevo valor almacenado.

```
class Cliente {
  nombreCliente;
  dniCliente;
}
class CuentaCorriente {
  nroCuenta;
  saldoCuenta; 
  
  depositoEnCuenta(valor) {
    // this.saldoCuenta = this.saldoCuenta + valor
    this.saldoCuenta += valor;
  }
  retiroEnCuenta(valor) {
    this.saldoCuenta -= valor;
  }
}


const cliente1 = new Cliente();
cliente1.nombreCliente = "Tyrone Backyardigans";
cliente1.dniCliente = 12134;

const cuentaCorriente1 = new CuentaCorriente();
cuentaCorriente1.nroCuenta = 234567890;
cuentaCorriente1.saldoCuenta = 500;

 
console.log(cuentaCorriente1.saldoCuenta);
//haciendo un depósito
 cuentaCorriente1.depositoEnCuenta(300);
console.log(cuentaCorriente1.saldoCuenta);

// haciendo un retiro
 cuentaCorriente1.retiroEnCuenta(20);
console.log(cuentaCorriente1.saldoCuenta);
```
```
// imprime en la consola 
// 500
// 800
// 780
```


**clase Constructor**

Al crear un nuevo objeto _cuentaCorriente3_ , el valor por defecto es 0, sin embargo, debemos definirlo y declarlo pues sino nos sale un error en la consola.

Para evitar eso, creamos un constructor, en donde se colocará ese valor inicial con que empiezan nuestras operaciones. La consola leerá esa información y tomará todo lo que esté en el constructor como valores iniciales.

Este es un **atributo privado** pues solo se utilizará dentro de la clase donde se ubique el constructor.

```
class Cliente {
  nombreCliente;
  dniCliente;
}


class CuentaCorriente {
  nroCuenta;
  saldoCuenta; 
  
  constructor(){
    this.nroCuenta = "";
    this.saldoCuenta = 0;  
  }
  
  depositoEnCuenta(valor) {
    // this.saldoCuenta = this.saldoCuenta + valor
    this.saldoCuenta += valor;
  }
  retiroEnCuenta(valor) {
    this.saldoCuenta -= valor;
  }
}

const cuentaCorriente3 = new CuentaCorriente();
cuentaCorriente3.depositoEnCuenta(600);
console.log(cuentaCorriente3.saldoCuenta);
cuentaCorriente3.retiroEnCuenta(80);
console.log(cuentaCorriente3.saldoCuenta);

``` 
```
// imprime en la consola 
600
520
```


*Lo que aprendimos aquí:*

* Creación de métodos (comportamientos de las clases)
* Palabra clave **this**
* *Constructores* de las clases
* *Encapsulamiento*
* Propuesta de atributos privados en clases
* Retorno de resultados con **return**
