JavaRush /Blog Java /Random-ES /Firma del método

Firma del método

Publicado en el grupo Random-ES
¡Hola! Ya dominas la creación de tus propias clases, con campos y métodos. Hoy hablaremos en detalle sobre los métodos. Por supuesto, hemos hecho esto más de una vez en nuestras conferencias, pero hablamos principalmente de puntos generales. Hoy analizaremos literalmente los métodos "en partes": descubriremos en qué consisten, qué opciones existen para crearlos y cómo se puede gestionar todo esto :) ¡Vamos!Firma del método - 1

Firma del método

Todo el código que describe un método se llama declaración de método . Una firma de método incluye el nombre del método y los tipos de parámetros en un orden específico. La apariencia general del anuncio se puede describir de la siguiente manera:
модификатор доступа, тип возвращаемого значения, Nombre метода(список параметров) {
    // тело метода
}
Tomemos un ejemplo de declaraciones de varios métodos de la clase Dog.
public class Dog {

   String name;

   public Dog(String name) {
       this.name = name;
   }

   public static void main(String[] args) {
       Dog max = new Dog("máximo");
       max.woof();

   }

   public void woof() {
       System.out.println("Собака по имени " + name + " говорит \"Гав-гав!\"");
   }

   public void run(int meters) {
       System.out.println("Собака по имени " + name + " пробежала " + meters + " метров!");
   }

   public String getName() {
       return name;
   }
}

1. Modificador de acceso

El modificador de acceso siempre aparece primero. Todos los métodos de clase Dogestán designados por el modificador public. Es decir, podemos llamarlos desde cualquier otra clase:
public class Main {

   public static void main(String[] args) {

       Dog butch = new Dog("Бутч");
       butch.run(100);
   }

}
Los métodos de clase Dog, como puede ver, son fácilmente accesibles en la clase Main. Esto es posible gracias al modificador public. Hay otros modificadores en Java y no todos te permitirán usar un método dentro de otra clase. Hablaremos de ellos en otras conferencias. Lo principal es recordar de qué es responsable el modificador: la disponibilidad/inaccesibilidad del método en otras clases :)

2. La palabra clave estática

Uno de los métodos Dog, concretamente, main()se indica mediante la palabra clave static. Si existe, debe especificarse después del modificador de acceso. ¿Recuerda que en conferencias anteriores hablamos sobre variables de clase estáticas? Cuando se aplica a métodos, esta palabra tiene aproximadamente el mismo significado. Si un método se especifica como static, esto significa que se puede utilizar sin referencia a un objeto de clase específico. Y, de hecho, para ejecutar un método estático main()en una clase, Dogno es necesario crear una instancia Dog; se ejecuta sin ella. Si este método no fuera estático, para usarlo necesitaríamos primero crear un objeto.

3. Valor de retorno.

Si nuestro método debe devolver algo, indicamos el tipo de valor de retorno. Esto se puede ver en el ejemplo de un captador getName():
public String getName() {
   return name;
}
Devuelve un objeto de tipo String. Si el método no devuelve nada, se especifica la palabra clave en lugar del tipo void, como en el método woof():
public void woof() {
   System.out.println("Собака по имени " + name + " говорит \"Гав-гав!\"");
}

Métodos con el mismo nombre.

Hay situaciones en las que nuestro programa requiere varias opciones sobre cómo funciona un método. ¿Por qué no creamos nuestra propia inteligencia artificial? Amazon tiene a Alexa, Yandex tiene a Alice, entonces ¿por qué somos peores? :) En la película sobre Iron Man, Tony Stark creó su propia inteligencia artificial excepcional: JARVIS. Rindamos homenaje al maravilloso personaje y nombremos nuestra IA en su honor :) Lo primero que debemos enseñarle a Jarvis es saludar a las personas que entran a la habitación (sería extraño que un intelecto tan grande resultara ser descortés).
public class Jarvis {

   public void sayHi(String name) {
       System.out.println("Buenas noches, " + name + ", ¿Cómo estás?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
   }
}
Salida de consola:

Добрый вечер, Тони Старк, Cómo ваши дела?
¡Excelente! Jarvis sabe saludar a quien entra. La mayoría de las veces, por supuesto, será su dueño, Tony Stark. ¡Pero puede que no venga solo! Y nuestro método sayHi()toma solo un argumento como entrada. Y, en consecuencia, sólo podrá saludar a uno de los que vengan e ignorará al otro. No muy educado, ¿de acuerdo?:/ En este caso, para resolver el problema, simplemente podemos escribir 2 métodos en la clase con el mismo nombre, pero con diferentes parámetros:
public class Jarvis {

   public void sayHi(String firstGuest) {
       System.out.println("Buenas noches, " + firstGuest + ", ¿Cómo estás?");
   }

   public void sayHi(String firstGuest, String secondGuest) {
       System.out.println("Buenas noches, " + firstGuest + ", " + secondGuest + ", ¿Cómo estás?");
   }

}
Esto se llama sobrecarga de métodos . La sobrecarga permite que nuestro programa sea más flexible y se adapte a diferentes opciones de trabajo. Veamos cómo funciona:
public class Jarvis {

   public void sayHi(String firstGuest) {
       System.out.println("Buenas noches, " + firstGuest + ", ¿Cómo estás?");
   }

   public void sayHi(String firstGuest, String secondGuest) {
       System.out.println("Buenas noches, " + firstGuest + ", " + secondGuest + ", ¿Cómo estás?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       jarvis.sayHi("Tony Stark", "Capitan America");
   }
}
Salida de consola:

Добрый вечер, Тони Старк, Cómo ваши дела? 
Добрый вечер, Тони Старк, Капитан Америка, Cómo ваши дела?
Genial, ambas opciones funcionaron :) ¡Sin embargo, no resolvimos el problema! ¿Qué pasa si hay tres invitados? Por supuesto, podemos sobrecargar el método nuevamente sayHi()para aceptar los nombres de tres invitados. Pero puede haber 4 o 5. Y así hasta el infinito. ¿Existe otra forma de enseñarle a Jarvis a trabajar con cualquier cantidad de nombres, sin un millón de sobrecargas de métodos sayHi()? :/ ¡Por supuesto que sí! De lo contrario, ¿Java sería el lenguaje de programación más popular del mundo? ;)
public class Jarvis {

   public void sayHi(String...names) {

       for (String name: names) {
           System.out.println("Buenas noches, " + name + ", ¿Cómo estás?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       System.out.println();
       jarvis.sayHi("Tony Stark", "Capitan America");
   }
}
El registro ( String...names) pasado como parámetro nos permite indicar que se pasa una determinada cantidad de cadenas al método. No especificamos de antemano cuántos debería haber, por lo que el funcionamiento de nuestro método ahora se vuelve mucho más flexible:
public class Jarvis {

   public void sayHi(String...names) {

       for (String name: names) {
           System.out.println("Buenas noches, " + name + ", ¿Cómo estás?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark", "Capitan America", "Viuda negra", "Casco");
   }
}
Salida de consola:

Добрый вечер, Тони Старк, Cómo ваши дела? 
Добрый вечер, Капитан Америка, Cómo ваши дела? 
Добрый вечер, Черная Вдова, Cómo ваши дела? 
Добрый вечер, Халк, Cómo ваши дела?
Dentro del método, recorremos todos los argumentos y enviamos frases preparadas con nombres a la consola. Aquí utilizamos un bucle simplificado for-each(ya lo has encontrado). Es genial porque escribir String...namesen realidad significa que el compilador coloca todos los parámetros pasados ​​en una matriz. Por lo tanto, namespuede trabajar con una variable como con una matriz, incluso recorrerla en bucle. Además, ¡funcionará para cualquier número de líneas transferidas! Dos, diez, incluso mil: el método funcionará de forma fiable con cualquier número de invitados. Mucho más conveniente que hacer sobrecargas para todas las opciones posibles, ¿no estás de acuerdo? :) Pongamos otro ejemplo de sobrecarga de métodos. Agreguemos un método a Jarvis printInfoFromDatabase(). Imprimirá información sobre la persona desde la base de datos a la consola. Si la base de datos indica que una persona es un superhéroe o supervillano, esta información también se mostrará en pantalla:
public class Jarvis {

   public  void printInfoFromDatabase (String bio) {

       System.out.println(bio);
   }

   public void printInfoFromDatabase(String bio, boolean isEvil, String nickname) {

       System.out.println(bio);
       if (!isEvil) {
           System.out.println("Также известен Cómo супергерой " + nickname);
       } else {
           System.out.println("Также известен Cómo суперзлодей " + nickname);
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.printInfoFromDatabase("Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington");
       System.out.println();
       jarvis.printInfoFromDatabase("Макс Эйзенхарт. Рост 188см, вес 86 кг.", true, "Магнето");
   }
}
Conclusión:

Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington
Макс Эйзенхарт. Рост 188см, вес 86 кг 
Также известен Cómo суперзлодей Магнето
Así es como funciona nuestro método dependiendo de los datos que le pasemos. Otro punto importante:¡El orden de los argumentos importa! Digamos que nuestro método toma una cadena y un número como entrada:
public class Man {

   public static void sayYourAge(String greeting, int age) {
       System.out.println(greeting + " " + age);
   }

   public static void main(String[] args) {

       sayYourAge("Mi edad - ", 33);
       sayYourAge(33, "Mi edad - "); //¡error!
   }
}
Si un método sayYourAge()de clase Mantoma una cadena y un número como entrada, ¡este es el orden en el que deben pasarse en el programa! Si los pasamos en un orden diferente, el compilador arrojará un error y la persona no podrá saber su edad. Por cierto, ¡los constructores que cubrimos en la última lección también son métodos! También se pueden sobrecargar (crear varios constructores con diferentes conjuntos de argumentos) y para ellos el orden de paso de los argumentos también es de fundamental importancia. Métodos reales! :)

Cómo llamar a métodos con parámetros similares

Como sabes, en Java existe la palabra nulo. Al trabajar con él, es muy importante comprender que nulo no es ni un objeto ni un tipo de datos. Imaginemos que tenemos una clase Man y un método introduce()que declara el nombre y la edad de una persona. En este caso, la edad se puede transmitir en forma de texto o se puede expresar como un número.
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man sasha = new Man();
       sasha.introduce("Sasha", "двадцать один");

       Man masha = new Man();
       masha.introduce("Мария", 32);
   }
}
Ya estamos familiarizados con la sobrecarga, por lo que sabemos que el método funcionará como se esperaba en ambas ocasiones:

Меня зовут Саша, мой возраст - двадцать один 
Меня зовут Мария, мой возраст - 32 
Pero, ¿qué sucede si pasamos nulo como segundo parámetro, no una cadena o un número?
public static void main(String[] args) {

   Man victor = new Man();
   victor.introduce("Виктор", null);//Ambiguous method call!
}
¡Recibiremos un error de compilación! El error "Llamada a método ambiguo" se traduce como "llamada a método ambiguo". ¿Por qué podría surgir y cuál es la “ambigüedad”? En realidad es simple. La cuestión es que tenemos dos opciones para el método: with Stringy with Integercomo segundo argumento. ¡Pero ambos Stringy Integerpueden ser nulos! Para ambos tipos (ya que son tipos de referencia), nulo es el valor predeterminado. Es por eso que el compilador en esta situación no puede determinar qué versión del método debe llamar. Resolver este problema es bastante sencillo. El punto es que null se puede convertir explícitamente a un tipo de referencia específico. Por lo tanto, al llamar a un método, puede indicar entre paréntesis el tipo de datos que necesita para el segundo argumento. El compilador entenderá su "pista" y llamará al método requerido:
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Метод с двумя строками!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Метод со строкой и числом!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man victor = new Man();
       victor.introduce("Виктор", (String) null);
   }
}
Conclusión:

Метод с двумя строками! 
Меня зовут Виктор, мой возраст - null
Pero si el parámetro numérico fuera una primitiva inty no un objeto de tipo de referencia Integer, tal error no ocurriría.
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Метод с двумя строками!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, int age) {
       System.out.println("Метод со строкой и числом!!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man victor = new Man();
       victor.introduce("Виктор", null);
   }
}
¿Has adivinado por qué? Si lo adivinaste, bien hecho :) Porque las primitivas no pueden ser iguales a nulas. Ahora el compilador sólo tiene una opción para llamar al método introduce(): con dos líneas. Es esta versión del método la que se procesará cada vez que se llame al método.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION