"El tipo de argumento '¿Cadena?' no se puede asignar al tipo de parámetro 'Cadena'" cuando se usa stdin.readLineSync()
Soy nuevo en dardos. No sé qué tipo de error he cometido, pero este código no funcionó. Es un código simple, simplemente lea la edad en la terminal y diga que es menor o mayor de 18 años.
import 'dart:io';
main(){
print("Entre com a sua idade: ");
var input = stdin.readLineSync();
var idade = int.parse(input);
if(idade >= 18){
print("É maior de idade");
}else{
print("É menor de idade");
}
}
Y me sale este error:
algoritmo01.dart:15:25: Error: The argument type 'String?' can't be assigned to the parameter type 'String' because 'String?' is nullable and 'String' isn't.
var idade = int.parse(input);
Bienvenido a Dardo. Lo que está experimentando es la nueva característica de seguridad nula (introducida con Dart 2.12.0) donde las variables de forma predeterminada no pueden contener el valor nulo. Esto se verifica estáticamente, por lo que obtendrá un error incluso antes de que se ejecute su programa.
En su ejemplo el problema es la siguiente línea:
var input = stdin.readLineSync();
Si revisamos el manual podemos ver que este método tiene la siguiente firma:
String? readLineSync (
{Encoding encoding = systemEncoding,
bool retainNewlines = false}
)
https://api.dart.dev/stable/2.12.2/dart-io/Stdin/readLineSync.html
String?
significa que es un tipo que acepta valores NULL y, por lo tanto, se le permite contener cualquier cadena o nulo. Si el tipo fuera, String
significaría que el resultado solo puede ser a String
y never null
.
Esto significa que su variable input
ahora tiene el tipo String?
. Esto (introducido en 2.12.0) es un problema si observa la segunda línea de su ejemplo:
var idade = int.parse(input);
Dado que la firma de int.parse
es:
int parse (
String source,
{int? radix,
@deprecated int onError(
String source
)}
)
https://api.dart.dev/stable/2.12.2/dart-core/int/parse.html
Lo cual requiere un String
(que por lo tanto nunca puede ser null
). Por lo tanto, no se le permite dar su String?
parámetro as a un método que solo maneja archivos String
. Se habría permitido lo contrario (si el método toma String?
y le das un String
).
Entonces, ¿qué podemos hacer ante esta situación? Bueno, debes manejar el caso de null
o decirle a Dart que debería bloquear tu programa si input
es así null
.
Entonces podrías manejarlo como:
import 'dart:io';
void main() {
print("Entre com a sua idade: ");
var input = stdin.readLineSync();
if (input != null) {
var idade = int.parse(input);
if (idade >= 18) {
print("É maior de idade");
} else {
print("É menor de idade");
}
} else {
print('Input was null!');
}
}
Como puede ver, esto está permitido incluso si input
técnicamente siguen siendo del tipo String?
. Pero Dart puede ver que su if
declaración impedirá input
tener el valor null
, por lo que será "promovida" mientras String
esté dentro de esta declaración if.
Otra solución es decirle a Dart que debería dejar de quejarse de errores estáticos input
y simplemente asumir input
que es String
al compilar el código:
import 'dart:io';
void main() {
print("Entre com a sua idade: ");
var input = stdin.readLineSync()!;
var idade = int.parse(input);
if (idade >= 18) {
print("É maior de idade");
} else {
print("É menor de idade");
}
}
(El cambio se !
agrega después readLineSync()
)
En este caso, Dart agregará su propia null
verificación y bloqueará el programa si stdin.readLineSync
proporciona un null
valor. Esto es para garantizar que nunca daremos int.parse
un valor nulo que podría hacer que su código falle en otro lugar. Al agregar null
-check donde obtenemos el valor cuestionable, podemos asegurarnos de que fallamos rápidamente y en el lugar donde las cosas no fueron como esperábamos.
Puede leer mucho más sobre la seguridad nula en Dart aquí (también vinculado por Stephen): https://dart.dev/null-safety/understanding-null-safety
La respuesta aceptada es correcta. Pero existe otra solución alternativa. Puede utilizar el operador "si es nulo" como este:
var idade = int.parse(input ?? "-1");
Entonces el código completo se verá así:
import 'dart:io';
main(){
print("Entre com a sua idade: ");
var input = stdin.readLineSync();
var idade = int.parse(input ?? "-1");
if(idade >= 18){
print("É maior de idade");
}else if(idade < 18 && idade > 0){
print("É menor de idade");
} else {
print("entrada errada");
}
}