🧱 Programando con Objetos: Comportamiento

Además de estados, un objeto también tiene comportamiento, que sus clientes, es decir, quienes usan los objetos, pueden utilizar. Estos comportamientos de nuestro objeto son definidos mediante métodos dentro de la clase. Los métodos públicos son los únicos accesibles para los clientes de nuestro objeto. Ellos pueden ser llamados en cualquier momento luego de que el objeto fue creado. Algunos métodos devuelven algo a quien los llama. En ese caso un return type debe ser declarado (en caso de utilizar lenguajes tipados). Otros métodos nos retornaran nada. En ese caso el tipo de retorno será el tipo especial void (de nuevo en caso de utilizar lenguajes tipados).

  • 📋 Comportamientos de un objeto declarados como públicos
class Payment
{
  public someMethod(): number
  {
    return /* ... */;
  }
  
  public someOtherMethod(): void
  {
    // ...
  }
}

const object1 = new Payment();

const value = object1.someMethod(); // someMethod() retorna o devuelve un número que almacenaremos en la variable value.
object1.someOtherMethod(); // someOtherMethod() no retorna nada en específico, entonces el cliente en este caso no necesita almacenar nada.

Una clase puede contener definiciones de métodos privados. Esto funciona de la misma manera que las propiedades privadas. Cualquier instancia de una clase puede llamar a los métodos privados de cualquier otra instancia del mismo tipo de clase, incluída ella misma. Sin embargo, por lo general, los métodos privados se utilizan para representar pasos más pequeños en un proceso más grande.

  • 📋 Métodos privados
class Payment
{
  public someMethod(): number
  {
    const value = this.stepOne();
    return this.stepTwo(value);
  }
  
  private stepOne(): number
  {
    // ...
    
    return value;
  }
  
  private stepTwo(value: number): number
  {
    // ...
    
    return finalValue;
  }
}

const somePayment = new Payment();
const someValue = somePayment.someMethod(); // Funciona ya que es un método público.
const tryToUseInternalMethod = somePayment.stepTwo(10); // No funcionará ya que los clientes no tienen acceso a los métodos privados, al igual que las propiedades privadas.

Así como podemos definir parametros para nuestro constructor, también podemos definir parámetros para nuestros métodos. Luego quien lo llame deberá proporcionar un valor específico como argumento al llamar al método en cuestión. El método puede utilizar ese valor para determinar que hacer con él, puede pasarlo a un colaborador, colaborar con otra propiedad para hacer algo, ó puede utilizarlo para cambiar el valor de una propiedad.

  • 📋 Diferentes maneras donde los argumentos de los métodos pueden ser usados
class Payment
{
  private someNumber: number;
  
  public setNumber(newNumber: number): void // Aquí, newNumber será el nuevo valor asignado a la propiedad someNumber.
  {
    this.someNumber = newNumber;
  }
  
  public multiply(other: number): number // En este caso, other será multiplicado por el valor actual de la propiedad someNumber.
  {
    return this.someNumber * other;
  }
  
  private someOtherMethod(Gateway gateway): void // Aquí, otro objeto del tipo Gateway es pasado como argumento del método, entonces Payment puede realizar llamadas sobre sus métodos públicos.
  {
    gateway.doSomething();
  }
}

💡 Check for null arguments

Algunos lenguajes permiten que un cliente pase un valor null como argumento incluso si el tipo de un parámetro se ha declarado explícitamente. Entonces, en el ejemplo del código anterior, el argumento proporcionado para Gateway puede ser nulo, aunque se escriba como Gateway. Por lo tanto intentar llamar a doSomething() en el objeto Gateway siendo nulo, provocaría que se lanzara un NullPointerException.

Esta es la razón por la que siempre debe verificar si hay valores nulos o, preferiblemente, dejar que un compilador o un analizador estático nos advierta sobre posibles NullPointerExceptions en nuestro código. El lenguaje de programación que estamos utilizando por defecto no permite pasar null como argumento si tipamos que debe llegar X tipo como argumento.

En los ejemplos en los que queremos permitirlo, tenemos que declararlo explícitamente usando un union type en el tipo del parámetro que tiene el método. Esto también funciona para tipos de propiedad, y tipos de devolución, debemos usar Gateway | null por ejemplo:

class Payment
{
  private gateway: Gateway | null;
  
  private someOtherMethod(gateway: Gateway | null): Gateway | null
  {
    // ...
  }
}

En el caso particular de JavaScript y TypeScript tenemos un caso particular además del null que es el caso de undefined, lo veremos a continuación.

💡 Check for undefined arguments

Esto solo aplica para JavaScript y TypeScript

Podemos hacer uso del simbolo ‘?’ en el caso de argumentos de método o en la declaración de propiedades como símbolo de que es opcional esa variable, argumento de entrada, es decir, que puede contener un valor de cierto tipo o undefined.

Aclarar que esto en Typescript representa Opcional, es decir, ALGO ó UNDEFINED. No le podremos pasar un valor en null al utilizar la notación con ‘?’.

Forma 1:

class Payment
{
  private gateway: Gateway | undefined;
  
  private someOtherMethod(gateway: Gateway | undefined): Gateway | undefined
  {
    // ...
  }
}

Forma 2:

class Payment
{
  private gateway?: Gateway;
  
  private someOtherMethod(gateway?: Gateway): Gateway | undefined
  {
    // ...
  }
}

Particularmente que tenga que combinar ambas formas (‘?’ y union type) no me agrada demasiado pero es lo que hay actualmente, podrían crearse tipos propios para sintetizar estas opciones pero en todo caso lo veremos en otra lección si es necesario.

sign
Written on November 14, 2023